Merge "Only allow mediaserver to report video battery stats"
diff --git a/.gitignore b/.gitignore
index 481c592..c47cc8b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,4 @@
.idea
*.iml
*.sw*
+gen/
\ No newline at end of file
diff --git a/Android.bp b/Android.bp
index 7687270..1023b48 100644
--- a/Android.bp
+++ b/Android.bp
@@ -26,7 +26,35 @@
// READ ME: ########################################################
java_defaults {
+ name: "framework-aidl-export-defaults",
+
+ aidl: {
+ export_include_dirs: [
+ // From build/make/core/pathmap.mk FRAMEWORK_BASE_SUBDIRS
+ "core/java",
+ "graphics/java",
+ "location/java",
+ "lowpan/java",
+ "media/java",
+ "media/apex/java",
+ "media/mca/effect/java",
+ "media/mca/filterfw/java",
+ "media/mca/filterpacks/java",
+ "drm/java",
+ "opengl/java",
+ "sax/java",
+ "telecomm/java",
+ "telephony/java",
+ "wifi/java",
+ "keystore/java",
+ "rs/java",
+ ],
+ },
+}
+
+java_defaults {
name: "framework-defaults",
+ defaults: ["framework-aidl-export-defaults"],
installable: true,
srcs: [
@@ -78,9 +106,6 @@
"core/java/android/app/ISearchManagerCallback.aidl",
"core/java/android/app/IServiceConnection.aidl",
"core/java/android/app/IStopUserCallback.aidl",
- "core/java/android/app/job/IJobCallback.aidl",
- "core/java/android/app/job/IJobScheduler.aidl",
- "core/java/android/app/job/IJobService.aidl",
"core/java/android/app/ITransientNotification.aidl",
"core/java/android/app/IUidObserver.aidl",
"core/java/android/app/IUiAutomationConnection.aidl",
@@ -702,27 +727,6 @@
],
aidl: {
- export_include_dirs: [
- // From build/make/core/pathmap.mk FRAMEWORK_BASE_SUBDIRS
- "core/java",
- "graphics/java",
- "location/java",
- "lowpan/java",
- "media/java",
- "media/apex/java",
- "media/mca/effect/java",
- "media/mca/filterfw/java",
- "media/mca/filterpacks/java",
- "drm/java",
- "opengl/java",
- "sax/java",
- "telecomm/java",
- "telephony/java",
- "wifi/java",
- "keystore/java",
- "rs/java",
- ],
-
include_dirs: [
"system/update_engine/binder_bindings",
"frameworks/native/aidl/binder",
@@ -798,7 +802,10 @@
"--multi-dex",
],
- plugins: ["view-inspector-annotation-processor"],
+ plugins: [
+ "view-inspector-annotation-processor",
+ "staledataclass-annotation-processor",
+ ],
}
filegroup {
@@ -835,17 +842,40 @@
}
java_library {
- name: "framework",
+ name: "framework-minus-apex",
defaults: ["framework-defaults"],
javac_shard_size: 150,
+ required: [
+ "framework-platform-compat-config",
+ "libcore-platform-compat-config",
+ ],
+}
+
+java_library {
+ name: "framework",
+ defaults: ["framework-aidl-export-defaults"],
+ installable: true,
+ static_libs: [
+ "framework-minus-apex",
+ "jobscheduler-framework",
+ ],
+ sdk_version: "core_platform",
}
java_library {
name: "framework-annotation-proc",
defaults: ["framework-defaults"],
installable: false,
- // Use UsedByApps annotation processor
- plugins: ["unsupportedappusage-annotation-processor"],
+ plugins: [
+ "unsupportedappusage-annotation-processor",
+ "compat-changeid-annotation-processor",
+ ],
+}
+
+platform_compat_config {
+ name: "framework-platform-compat-config",
+ prefix: "framework",
+ src: ":framework-annotation-proc",
}
// A library including just UnsupportedAppUsage.java classes.
@@ -1356,8 +1386,9 @@
":updatable-media-srcs-without-aidls",
"test-mock/src/**/*.java",
"test-runner/src/**/*.java",
+ ":jobscheduler-framework-source",
],
- srcs_lib: "framework",
+ srcs_lib: "framework-minus-apex",
srcs_lib_whitelist_dirs: frameworks_base_subdirs,
srcs_lib_whitelist_pkgs: packages_to_document,
libs: framework_docs_only_libs,
@@ -1413,8 +1444,9 @@
":opt-net-voip-srcs",
":core_public_api_files",
":updatable-media-srcs-without-aidls",
+ ":jobscheduler-framework-source",
],
- srcs_lib: "framework",
+ srcs_lib: "framework-minus-apex",
srcs_lib_whitelist_dirs: frameworks_base_subdirs,
srcs_lib_whitelist_pkgs: packages_to_document,
local_sourcepaths: frameworks_base_subdirs,
diff --git a/apct-tests/perftests/core/src/android/wm/RecentsAnimationPerfTest.java b/apct-tests/perftests/core/src/android/wm/RecentsAnimationPerfTest.java
index 4e2b281..2b6f455 100644
--- a/apct-tests/perftests/core/src/android/wm/RecentsAnimationPerfTest.java
+++ b/apct-tests/perftests/core/src/android/wm/RecentsAnimationPerfTest.java
@@ -26,6 +26,7 @@
import static org.hamcrest.core.Is.is;
import android.app.Activity;
+import android.app.ActivityManager.TaskSnapshot;
import android.app.ActivityTaskManager;
import android.app.IActivityTaskManager;
import android.content.ComponentName;
@@ -216,7 +217,7 @@
}
@Override
- public void onAnimationCanceled(boolean deferredWithScreenshot) throws RemoteException {
+ public void onAnimationCanceled(TaskSnapshot taskSnapshot) throws RemoteException {
Assume.assumeNoException(
new AssertionError("onAnimationCanceled should not be called"));
}
diff --git a/apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTests.java b/apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTests.java
index 2fe0ee7..4b7a7f6 100644
--- a/apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTests.java
+++ b/apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTests.java
@@ -15,6 +15,8 @@
*/
package android.multiuser;
+import static org.junit.Assume.assumeTrue;
+
import android.app.ActivityManager;
import android.app.ActivityTaskManager;
import android.app.AppGlobals;
@@ -86,7 +88,9 @@
private UserManager mUm;
private ActivityManager mAm;
private IActivityManager mIam;
+ private PackageManager mPm;
private ArrayList<Integer> mUsersToRemove;
+ private boolean mHasManagedUserFeature;
private final BenchmarkRunner mRunner = new BenchmarkRunner();
@Rule
@@ -99,6 +103,8 @@
mAm = context.getSystemService(ActivityManager.class);
mIam = ActivityManager.getService();
mUsersToRemove = new ArrayList<>();
+ mPm = context.getPackageManager();
+ mHasManagedUserFeature = mPm.hasSystemFeature(PackageManager.FEATURE_MANAGED_USERS);
}
@After
@@ -260,6 +266,8 @@
/** Tests creating a new profile. */
@Test
public void managedProfileCreate() throws Exception {
+ assumeTrue(mHasManagedUserFeature);
+
while (mRunner.keepRunning()) {
final int userId = createManagedProfile();
@@ -273,6 +281,8 @@
/** Tests starting (unlocking) a newly-created profile. */
@Test
public void managedProfileUnlock() throws Exception {
+ assumeTrue(mHasManagedUserFeature);
+
while (mRunner.keepRunning()) {
mRunner.pauseTiming();
final int userId = createManagedProfile();
@@ -289,6 +299,8 @@
/** Tests starting (unlocking) an already-created, but no-longer-running, profile. */
@Test
public void managedProfileUnlock_stopped() throws Exception {
+ assumeTrue(mHasManagedUserFeature);
+
while (mRunner.keepRunning()) {
mRunner.pauseTiming();
final int userId = createManagedProfile();
@@ -310,6 +322,8 @@
*/
@Test
public void managedProfileUnlockAndLaunchApp() throws Exception {
+ assumeTrue(mHasManagedUserFeature);
+
while (mRunner.keepRunning()) {
mRunner.pauseTiming();
final int userId = createManagedProfile();
@@ -334,6 +348,8 @@
*/
@Test
public void managedProfileUnlockAndLaunchApp_stopped() throws Exception {
+ assumeTrue(mHasManagedUserFeature);
+
while (mRunner.keepRunning()) {
mRunner.pauseTiming();
final int userId = createManagedProfile();
@@ -357,6 +373,8 @@
/** Tests installing a pre-existing app in a newly-created profile. */
@Test
public void managedProfileInstall() throws Exception {
+ assumeTrue(mHasManagedUserFeature);
+
while (mRunner.keepRunning()) {
mRunner.pauseTiming();
final int userId = createManagedProfile();
@@ -376,6 +394,8 @@
*/
@Test
public void managedProfileCreateUnlockInstallAndLaunchApp() throws Exception {
+ assumeTrue(mHasManagedUserFeature);
+
final String packageName = "perftests.multiuser.apps.dummyapp";
while (mRunner.keepRunning()) {
mRunner.pauseTiming();
@@ -396,6 +416,8 @@
/** Tests stopping a profile. */
@Test
public void managedProfileStopped() throws Exception {
+ assumeTrue(mHasManagedUserFeature);
+
while (mRunner.keepRunning()) {
mRunner.pauseTiming();
final int userId = createManagedProfile();
diff --git a/apex/jobscheduler/OWNERS b/apex/jobscheduler/OWNERS
new file mode 100644
index 0000000..d004eed
--- /dev/null
+++ b/apex/jobscheduler/OWNERS
@@ -0,0 +1,6 @@
+yamasani@google.com
+omakoto@google.com
+ctate@android.com
+ctate@google.com
+kwekua@google.com
+suprabh@google.com
\ No newline at end of file
diff --git a/apex/jobscheduler/README_js-mainline.md b/apex/jobscheduler/README_js-mainline.md
index b5fea5e..c1ad666 100644
--- a/apex/jobscheduler/README_js-mainline.md
+++ b/apex/jobscheduler/README_js-mainline.md
@@ -6,46 +6,33 @@
- http://go/moving-js-code-for-mainline
- http://go/jobscheduler-code-dependencies-2019-07
-- [ ] Move client code
- - [ ] Move code
- - [ ] Make build file
- - [ ] "m jobscheduler-framework" pass
- - [ ] "m framework" pass
- - [ ] "m service" pass
-- [ ] Move proto
- - No, couldn't do it, because it's referred to by incidentd_proto
-- [ ] Move service
- - [X] Move code (done, but it won't compile yet)
- - [X] Make build file
- - [X] "m service" pass
- - [X] "m jobscheduler-service" pass
- - To make it pass, jobscheduler-service has to link services.jar too. Many dependencies.
- [ ] Move this into `frameworks/apex/jobscheduler/...`. Currently it's in `frameworks/base/apex/...`
because `frameworks/apex/` is not a part of any git projects. (and also working on multiple
projects is a pain.)
+## Current structure
-## Problems
-- Couldn't move dumpsys proto files. They are used by incidentd_proto, which is in the platform
- (not updatable).
- - One idea is *not* to move the proto files into apex but keep them in the platform.
- Then we make sure to extend the proto files in a backward-compat way (which we do anyway)
- and always use the latest file from the JS apex.
+- JS service side classes are put in `jobscheduler-service.jar`.
+It's *not* included in services.jar, and instead it's put in the system server classpath,
+which currently looks like the following:
+`SYSTEMSERVERCLASSPATH=/system/framework/services.jar:/system/framework/jobscheduler-service.jar:/system/framework/ethernet-service.jar:/system/framework/wifi-service.jar:/system/framework/com.android.location.provider.jar`
-- There are a lot of build tasks that use "framework.jar". (Examples: hiddenapi-greylist.txt check,
- update-api / public API check and SDK stub (android.jar) creation)
- To make the downstream build modules buildable, we need to include js-framework.jar in
- framework.jar. However it turned out to be tricky because soong has special logic for "framework"
- and "framework.jar".
- i.e. Conceptually, we can do it by renaming `framework` to `framework-minus-jobscheduler`, build
- `jobscheduler-framework` with `framework-minus-jobscheduler`, and create `framework` by merging
- `framework-minus-jobscheduler` and `jobscheduler-framework`.
- However it didn't quite work because of the special casing.
+ (Note `jobscheduler-service.jar` will be put at the end in http://ag/9128109)
-- JS-service uses a lot of other code in `services`, so it needs to link services.core.jar e.g.
- - Common system service code, e.g. `com.android.server.SystemService`
- - Common utility code, e.g. `FgThread` and `IoThread`
- - Other system services such as `DeviceIdleController` and `ActivityManagerService`
- - Server side singleton. `AppStateTracker`
- - `DeviceIdleController.LocalService`, which is a local service but there's no interface class.
- - `XxxInternal` interfaces that are not in the framework side. -> We should be able to move them.
+ `SYSTEMSERVERCLASSPATH` is generated from `PRODUCT_SYSTEM_SERVER_JARS`.
+
+- JS framework side classes are put in `jobscheduler-framework.jar`,
+and the rest of the framework code is put in `framework-minus-apex.jar`,
+as of http://ag/9145619.
+
+ However these jar files are *not* put on the device. We still generate
+ `framework.jar` merging the two jar files, and this jar file is what's
+ put on the device and loaded by Zygote.
+
+
+This is *not* the final design. From a gerrit comment on http://ag/9145619:
+
+> This CL is just the first step, and the current state isn't not really the final form. For now we just want to have two separate jars, which makes it easier for us to analyze dependencies between them, and I wanted to minimize the change to the rest of the system. So, for example, zygote will still only have "framework.jar" in its classpath, instead of the two jars for now.
+> But yes, eventually, we won't even be able to have the monolithic "framework.jar" file because of mainline, so we need to figure out how to build the system without creating it. At that point zygote will have the two separate jar files in its classpath.
+> When we reach that point, we should revisit the naming of it, and yes, maybe the simple "framework.jar" is a good option.
+> But again, for now, I want to make this change as transparent as possible to the rest of the world.
diff --git a/apex/jobscheduler/framework/Android.bp b/apex/jobscheduler/framework/Android.bp
new file mode 100644
index 0000000..bdb5248
--- /dev/null
+++ b/apex/jobscheduler/framework/Android.bp
@@ -0,0 +1,29 @@
+filegroup {
+ name: "jobscheduler-framework-source",
+ srcs: [
+ "java/**/*.java",
+ "java/android/app/job/IJobCallback.aidl",
+ "java/android/app/job/IJobScheduler.aidl",
+ "java/android/app/job/IJobService.aidl",
+ ],
+ path: "java",
+}
+
+java_library {
+ name: "jobscheduler-framework",
+ installable: true,
+ sdk_version: "core_platform",
+
+ srcs: [
+ ":jobscheduler-framework-source",
+ ],
+
+ aidl: {
+ export_include_dirs: [
+ "java",
+ ],
+ },
+ libs: [
+ "framework-minus-apex",
+ ],
+}
diff --git a/core/java/android/app/JobSchedulerImpl.java b/apex/jobscheduler/framework/java/android/app/JobSchedulerImpl.java
similarity index 95%
rename from core/java/android/app/JobSchedulerImpl.java
rename to apex/jobscheduler/framework/java/android/app/JobSchedulerImpl.java
index 924a708..f59e7a4 100644
--- a/core/java/android/app/JobSchedulerImpl.java
+++ b/apex/jobscheduler/framework/java/android/app/JobSchedulerImpl.java
@@ -14,7 +14,6 @@
* limitations under the License.
*/
-// in android.app so ContextImpl has package access
package android.app;
import android.app.job.IJobScheduler;
@@ -27,10 +26,12 @@
import java.util.List;
-// APEX NOTE: Class path referred to by robolectric, so can't move it.
-
/**
* Concrete implementation of the JobScheduler interface
+ *
+ * Note android.app.job is the better package to put this class, but we can't move it there
+ * because that'd break robolectric. Grr.
+ *
* @hide
*/
public class JobSchedulerImpl extends JobScheduler {
diff --git a/core/java/android/app/job/IJobCallback.aidl b/apex/jobscheduler/framework/java/android/app/job/IJobCallback.aidl
similarity index 100%
rename from core/java/android/app/job/IJobCallback.aidl
rename to apex/jobscheduler/framework/java/android/app/job/IJobCallback.aidl
diff --git a/core/java/android/app/job/IJobScheduler.aidl b/apex/jobscheduler/framework/java/android/app/job/IJobScheduler.aidl
similarity index 100%
rename from core/java/android/app/job/IJobScheduler.aidl
rename to apex/jobscheduler/framework/java/android/app/job/IJobScheduler.aidl
diff --git a/core/java/android/app/job/IJobService.aidl b/apex/jobscheduler/framework/java/android/app/job/IJobService.aidl
similarity index 100%
rename from core/java/android/app/job/IJobService.aidl
rename to apex/jobscheduler/framework/java/android/app/job/IJobService.aidl
diff --git a/core/java/android/app/job/JobInfo.aidl b/apex/jobscheduler/framework/java/android/app/job/JobInfo.aidl
similarity index 100%
rename from core/java/android/app/job/JobInfo.aidl
rename to apex/jobscheduler/framework/java/android/app/job/JobInfo.aidl
diff --git a/core/java/android/app/job/JobInfo.java b/apex/jobscheduler/framework/java/android/app/job/JobInfo.java
similarity index 100%
rename from core/java/android/app/job/JobInfo.java
rename to apex/jobscheduler/framework/java/android/app/job/JobInfo.java
diff --git a/core/java/android/app/job/JobParameters.aidl b/apex/jobscheduler/framework/java/android/app/job/JobParameters.aidl
similarity index 100%
rename from core/java/android/app/job/JobParameters.aidl
rename to apex/jobscheduler/framework/java/android/app/job/JobParameters.aidl
diff --git a/core/java/android/app/job/JobParameters.java b/apex/jobscheduler/framework/java/android/app/job/JobParameters.java
similarity index 94%
rename from core/java/android/app/job/JobParameters.java
rename to apex/jobscheduler/framework/java/android/app/job/JobParameters.java
index dadfe3d..150cdbc 100644
--- a/core/java/android/app/job/JobParameters.java
+++ b/apex/jobscheduler/framework/java/android/app/job/JobParameters.java
@@ -50,6 +50,24 @@
/** @hide */
public static final int REASON_DEVICE_THERMAL = JobProtoEnums.STOP_REASON_DEVICE_THERMAL; // 5.
+ /**
+ * All the stop reason codes. This should be regarded as an immutable array at runtime.
+ *
+ * Note the order of these values will affect "dumpsys batterystats", and we do not want to
+ * change the order of existing fields, so adding new fields is okay but do not remove or
+ * change existing fields. When deprecating a field, just replace that with "-1" in this array.
+ *
+ * @hide
+ */
+ public static final int[] JOB_STOP_REASON_CODES = {
+ REASON_CANCELED,
+ REASON_CONSTRAINTS_NOT_SATISFIED,
+ REASON_PREEMPT,
+ REASON_TIMEOUT,
+ REASON_DEVICE_IDLE,
+ REASON_DEVICE_THERMAL,
+ };
+
/** @hide */
public static String getReasonName(int reason) {
switch (reason) {
@@ -58,6 +76,7 @@
case REASON_PREEMPT: return "preempt";
case REASON_TIMEOUT: return "timeout";
case REASON_DEVICE_IDLE: return "device_idle";
+ case REASON_DEVICE_THERMAL: return "thermal";
default: return "unknown:" + reason;
}
}
diff --git a/core/java/android/app/job/JobScheduler.java b/apex/jobscheduler/framework/java/android/app/job/JobScheduler.java
similarity index 100%
rename from core/java/android/app/job/JobScheduler.java
rename to apex/jobscheduler/framework/java/android/app/job/JobScheduler.java
diff --git a/core/java/android/app/job/JobSchedulerFrameworkInitializer.java b/apex/jobscheduler/framework/java/android/app/job/JobSchedulerFrameworkInitializer.java
similarity index 87%
rename from core/java/android/app/job/JobSchedulerFrameworkInitializer.java
rename to apex/jobscheduler/framework/java/android/app/job/JobSchedulerFrameworkInitializer.java
index cf2979c..c90b872 100644
--- a/core/java/android/app/job/JobSchedulerFrameworkInitializer.java
+++ b/apex/jobscheduler/framework/java/android/app/job/JobSchedulerFrameworkInitializer.java
@@ -19,6 +19,7 @@
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
@@ -31,5 +32,8 @@
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/core/java/android/app/job/JobService.java b/apex/jobscheduler/framework/java/android/app/job/JobService.java
similarity index 100%
rename from core/java/android/app/job/JobService.java
rename to apex/jobscheduler/framework/java/android/app/job/JobService.java
diff --git a/core/java/android/app/job/JobServiceEngine.java b/apex/jobscheduler/framework/java/android/app/job/JobServiceEngine.java
similarity index 100%
rename from core/java/android/app/job/JobServiceEngine.java
rename to apex/jobscheduler/framework/java/android/app/job/JobServiceEngine.java
diff --git a/core/java/android/app/job/JobSnapshot.aidl b/apex/jobscheduler/framework/java/android/app/job/JobSnapshot.aidl
similarity index 100%
rename from core/java/android/app/job/JobSnapshot.aidl
rename to apex/jobscheduler/framework/java/android/app/job/JobSnapshot.aidl
diff --git a/core/java/android/app/job/JobSnapshot.java b/apex/jobscheduler/framework/java/android/app/job/JobSnapshot.java
similarity index 100%
rename from core/java/android/app/job/JobSnapshot.java
rename to apex/jobscheduler/framework/java/android/app/job/JobSnapshot.java
diff --git a/core/java/android/app/job/JobWorkItem.aidl b/apex/jobscheduler/framework/java/android/app/job/JobWorkItem.aidl
similarity index 100%
rename from core/java/android/app/job/JobWorkItem.aidl
rename to apex/jobscheduler/framework/java/android/app/job/JobWorkItem.aidl
diff --git a/core/java/android/app/job/JobWorkItem.java b/apex/jobscheduler/framework/java/android/app/job/JobWorkItem.java
similarity index 100%
rename from core/java/android/app/job/JobWorkItem.java
rename to apex/jobscheduler/framework/java/android/app/job/JobWorkItem.java
diff --git a/core/java/com/android/server/job/JobSchedulerInternal.java b/apex/jobscheduler/framework/java/com/android/server/job/JobSchedulerInternal.java
similarity index 71%
rename from core/java/com/android/server/job/JobSchedulerInternal.java
rename to apex/jobscheduler/framework/java/com/android/server/job/JobSchedulerInternal.java
index dbf3b98..eefb9fa 100644
--- a/core/java/com/android/server/job/JobSchedulerInternal.java
+++ b/apex/jobscheduler/framework/java/com/android/server/job/JobSchedulerInternal.java
@@ -17,6 +17,7 @@
package com.android.server.job;
import android.app.job.JobInfo;
+import android.util.proto.ProtoOutputStream;
import java.util.List;
@@ -89,5 +90,30 @@
+ countSystemServerJobsSaved + "/"
+ countSystemSyncManagerJobsSaved;
}
+
+ /**
+ * Write the persist stats to the specified field.
+ */
+ public void writeToProto(ProtoOutputStream proto, long fieldId) {
+ final long token = proto.start(fieldId);
+
+ final long flToken = proto.start(JobStorePersistStatsProto.FIRST_LOAD);
+ proto.write(JobStorePersistStatsProto.Stats.NUM_TOTAL_JOBS, countAllJobsLoaded);
+ proto.write(JobStorePersistStatsProto.Stats.NUM_SYSTEM_SERVER_JOBS,
+ countSystemServerJobsLoaded);
+ proto.write(JobStorePersistStatsProto.Stats.NUM_SYSTEM_SYNC_MANAGER_JOBS,
+ countSystemSyncManagerJobsLoaded);
+ proto.end(flToken);
+
+ final long lsToken = proto.start(JobStorePersistStatsProto.LAST_SAVE);
+ proto.write(JobStorePersistStatsProto.Stats.NUM_TOTAL_JOBS, countAllJobsSaved);
+ proto.write(JobStorePersistStatsProto.Stats.NUM_SYSTEM_SERVER_JOBS,
+ countSystemServerJobsSaved);
+ proto.write(JobStorePersistStatsProto.Stats.NUM_SYSTEM_SYNC_MANAGER_JOBS,
+ countSystemSyncManagerJobsSaved);
+ proto.end(lsToken);
+
+ proto.end(token);
+ }
}
}
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobConcurrencyManager.java b/apex/jobscheduler/service/java/com/android/server/job/JobConcurrencyManager.java
index bec1947..525fbae 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobConcurrencyManager.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobConcurrencyManager.java
@@ -480,7 +480,7 @@
pw.print(mEffectiveInteractiveState ? "ON" : "OFF");
pw.println();
- pw.print("Last screen ON : ");
+ pw.print("Last screen ON: ");
TimeUtils.dumpTimeWithDelta(pw, now - nowRealtime + mLastScreenOnRealtime, now);
pw.println();
@@ -509,9 +509,8 @@
public void dumpProtoLocked(ProtoOutputStream proto, long tag, long now, long nowRealtime) {
final long token = proto.start(tag);
- proto.write(JobConcurrencyManagerProto.CURRENT_INTERACTIVE,
- mCurrentInteractiveState);
- proto.write(JobConcurrencyManagerProto.EFFECTIVE_INTERACTIVE,
+ proto.write(JobConcurrencyManagerProto.CURRENT_INTERACTIVE_STATE, mCurrentInteractiveState);
+ proto.write(JobConcurrencyManagerProto.EFFECTIVE_INTERACTIVE_STATE,
mEffectiveInteractiveState);
proto.write(JobConcurrencyManagerProto.TIME_SINCE_LAST_SCREEN_ON_MS,
@@ -521,8 +520,9 @@
mJobCountTracker.dumpProto(proto, JobConcurrencyManagerProto.JOB_COUNT_TRACKER);
- proto.write(JobConcurrencyManagerProto.MEMORY_TRIM_LEVEL,
- mLastMemoryTrimLevel);
+ proto.write(JobConcurrencyManagerProto.MEMORY_TRIM_LEVEL, mLastMemoryTrimLevel);
+
+ mStatLogger.dumpProto(proto, JobConcurrencyManagerProto.STATS);
proto.end(token);
}
@@ -676,19 +676,14 @@
+ " Res BG: %d"
+ " Starting: %d / %d (%d)"
+ " Total: %d%s / %d%s (%d%s)",
- mConfigNumMaxTotalJobs,
- mConfigNumMinBgJobs,
- mConfigNumMaxBgJobs,
+ mConfigNumMaxTotalJobs, mConfigNumMinBgJobs, mConfigNumMaxBgJobs,
- mNumRunningFgJobs, mNumRunningBgJobs,
- mNumRunningFgJobs + mNumRunningBgJobs,
+ mNumRunningFgJobs, mNumRunningBgJobs, mNumRunningFgJobs + mNumRunningBgJobs,
- mNumPendingFgJobs, mNumPendingBgJobs,
- mNumPendingFgJobs + mNumPendingBgJobs,
+ mNumPendingFgJobs, mNumPendingBgJobs, mNumPendingFgJobs + mNumPendingBgJobs,
mNumActualMaxFgJobs, (totalFg <= mConfigNumMaxTotalJobs) ? "" : "*",
mNumActualMaxBgJobs, (totalBg <= mConfigNumMaxBgJobs) ? "" : "*",
-
mNumActualMaxFgJobs + mNumActualMaxBgJobs,
(mNumActualMaxFgJobs + mNumActualMaxBgJobs <= mConfigNumMaxTotalJobs)
? "" : "*",
@@ -716,6 +711,14 @@
proto.write(JobCountTrackerProto.NUM_PENDING_FG_JOBS, mNumPendingFgJobs);
proto.write(JobCountTrackerProto.NUM_PENDING_BG_JOBS, mNumPendingBgJobs);
+ proto.write(JobCountTrackerProto.NUM_ACTUAL_MAX_FG_JOBS, mNumActualMaxFgJobs);
+ proto.write(JobCountTrackerProto.NUM_ACTUAL_MAX_BG_JOBS, mNumActualMaxBgJobs);
+
+ proto.write(JobCountTrackerProto.NUM_RESERVED_FOR_BG, mNumReservedForBg);
+
+ proto.write(JobCountTrackerProto.NUM_STARTING_FG_JOBS, mNumStartingFgJobs);
+ proto.write(JobCountTrackerProto.NUM_STARTING_BG_JOBS, mNumStartingBgJobs);
+
proto.end(token);
}
}
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 38bb75f..5ba563c 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
@@ -1943,7 +1943,7 @@
} catch (RemoteException e) {
}
if (mConstants.MIN_READY_NON_ACTIVE_JOBS_COUNT > 1
- && job.getStandbyBucket() != ACTIVE_INDEX
+ && job.getEffectiveStandbyBucket() != ACTIVE_INDEX
&& (job.getFirstForceBatchedTimeElapsed() == 0
|| sElapsedRealtimeClock.millis() - job.getFirstForceBatchedTimeElapsed()
< mConstants.MAX_NON_ACTIVE_JOB_BATCH_DELAY_MS)) {
@@ -3011,6 +3011,8 @@
pw.print(job.isReady());
pw.print(" user=");
pw.print(areUsersStartedLocked(job));
+ pw.print(" !thermal=");
+ pw.print(!isJobThermalConstrainedLocked(job));
pw.print(" !pending=");
pw.print(!mPendingJobs.contains(job));
pw.print(" !active=");
@@ -3018,15 +3020,7 @@
pw.print(" !backingup=");
pw.print(!(mBackingUpUids.indexOfKey(job.getSourceUid()) >= 0));
pw.print(" comp=");
- boolean componentPresent = false;
- try {
- componentPresent = (AppGlobals.getPackageManager().getServiceInfo(
- job.getServiceComponent(),
- PackageManager.MATCH_DEBUG_TRIAGED_MISSING,
- job.getUserId()) != null);
- } catch (RemoteException e) {
- }
- pw.print(componentPresent);
+ pw.print(isComponentUsable(job));
pw.println(")");
}
} else {
@@ -3177,27 +3171,24 @@
job.dump(proto, JobSchedulerServiceDumpProto.RegisteredJob.DUMP, true, nowElapsed);
- // isReadyToBeExecuted
+ proto.write(
+ JobSchedulerServiceDumpProto.RegisteredJob.IS_JOB_READY_TO_BE_EXECUTED,
+ isReadyToBeExecutedLocked(job));
proto.write(JobSchedulerServiceDumpProto.RegisteredJob.IS_JOB_READY,
job.isReady());
- proto.write(JobSchedulerServiceDumpProto.RegisteredJob.IS_USER_STARTED,
+ proto.write(JobSchedulerServiceDumpProto.RegisteredJob.ARE_USERS_STARTED,
areUsersStartedLocked(job));
+ proto.write(
+ JobSchedulerServiceDumpProto.RegisteredJob.IS_JOB_THERMAL_CONSTRAINED,
+ isJobThermalConstrainedLocked(job));
proto.write(JobSchedulerServiceDumpProto.RegisteredJob.IS_JOB_PENDING,
mPendingJobs.contains(job));
proto.write(JobSchedulerServiceDumpProto.RegisteredJob.IS_JOB_CURRENTLY_ACTIVE,
isCurrentlyActiveLocked(job));
proto.write(JobSchedulerServiceDumpProto.RegisteredJob.IS_UID_BACKING_UP,
mBackingUpUids.indexOfKey(job.getSourceUid()) >= 0);
- boolean componentPresent = false;
- try {
- componentPresent = (AppGlobals.getPackageManager().getServiceInfo(
- job.getServiceComponent(),
- PackageManager.MATCH_DEBUG_TRIAGED_MISSING,
- job.getUserId()) != null);
- } catch (RemoteException e) {
- }
- proto.write(JobSchedulerServiceDumpProto.RegisteredJob.IS_COMPONENT_PRESENT,
- componentPresent);
+ proto.write(JobSchedulerServiceDumpProto.RegisteredJob.IS_COMPONENT_USABLE,
+ isComponentUsable(job));
proto.end(rjToken);
}
@@ -3234,7 +3225,7 @@
job.writeToShortProto(proto, PendingJob.INFO);
job.dump(proto, PendingJob.DUMP, false, nowElapsed);
proto.write(PendingJob.EVALUATED_PRIORITY, evaluateJobPriorityLocked(job));
- proto.write(PendingJob.ENQUEUED_DURATION_MS, nowUptime - job.madePending);
+ proto.write(PendingJob.PENDING_DURATION_MS, nowUptime - job.madePending);
proto.end(pjToken);
}
@@ -3283,6 +3274,8 @@
}
mConcurrencyManager.dumpProtoLocked(proto,
JobSchedulerServiceDumpProto.CONCURRENCY_MANAGER, now, nowElapsed);
+
+ mJobs.getPersistStats().writeToProto(proto, JobSchedulerServiceDumpProto.PERSIST_STATS);
}
proto.flush();
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/BackgroundJobsController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/BackgroundJobsController.java
index b698e5b..8b61006 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/BackgroundJobsController.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/BackgroundJobsController.java
@@ -115,32 +115,27 @@
final long mToken = proto.start(StateControllerProto.BACKGROUND);
mAppStateTracker.dumpProto(proto,
- StateControllerProto.BackgroundJobsController.FORCE_APP_STANDBY_TRACKER);
+ StateControllerProto.BackgroundJobsController.APP_STATE_TRACKER);
mService.getJobStore().forEachJob(predicate, (jobStatus) -> {
final long jsToken =
proto.start(StateControllerProto.BackgroundJobsController.TRACKED_JOBS);
- jobStatus.writeToShortProto(proto,
- TrackedJob.INFO);
+ jobStatus.writeToShortProto(proto, TrackedJob.INFO);
final int sourceUid = jobStatus.getSourceUid();
proto.write(TrackedJob.SOURCE_UID, sourceUid);
final String sourcePkg = jobStatus.getSourcePackageName();
proto.write(TrackedJob.SOURCE_PACKAGE_NAME, sourcePkg);
- proto.write(TrackedJob.IS_IN_FOREGROUND,
- mAppStateTracker.isUidActive(sourceUid));
+ proto.write(TrackedJob.IS_IN_FOREGROUND, mAppStateTracker.isUidActive(sourceUid));
proto.write(TrackedJob.IS_WHITELISTED,
mAppStateTracker.isUidPowerSaveWhitelisted(sourceUid) ||
mAppStateTracker.isUidTempPowerSaveWhitelisted(sourceUid));
- proto.write(
- TrackedJob.CAN_RUN_ANY_IN_BACKGROUND,
- mAppStateTracker.isRunAnyInBackgroundAppOpsAllowed(
- sourceUid, sourcePkg));
+ proto.write(TrackedJob.CAN_RUN_ANY_IN_BACKGROUND,
+ mAppStateTracker.isRunAnyInBackgroundAppOpsAllowed(sourceUid, sourcePkg));
- proto.write(
- TrackedJob.ARE_CONSTRAINTS_SATISFIED,
+ proto.write(TrackedJob.ARE_CONSTRAINTS_SATISFIED,
(jobStatus.satisfiedConstraints &
JobStatus.CONSTRAINT_BACKGROUND_NOT_RESTRICTED) != 0);
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java
index a67aadf..43e8dfb 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java
@@ -631,6 +631,18 @@
final long token = proto.start(fieldId);
final long mToken = proto.start(StateControllerProto.CONNECTIVITY);
+ for (int i = 0; i < mRequestedWhitelistJobs.size(); i++) {
+ proto.write(
+ StateControllerProto.ConnectivityController.REQUESTED_STANDBY_EXCEPTION_UIDS,
+ mRequestedWhitelistJobs.keyAt(i));
+ }
+ for (int i = 0; i < mAvailableNetworks.size(); i++) {
+ Network network = mAvailableNetworks.valueAt(i);
+ if (network != null) {
+ network.writeToProto(proto,
+ StateControllerProto.ConnectivityController.AVAILABLE_NETWORKS);
+ }
+ }
for (int i = 0; i < mTrackedJobs.size(); i++) {
final ArraySet<JobStatus> jobs = mTrackedJobs.valueAt(i);
for (int j = 0; j < jobs.size(); j++) {
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/DeviceIdleJobsController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/DeviceIdleJobsController.java
index 127a5c8..0b67971 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/DeviceIdleJobsController.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/DeviceIdleJobsController.java
@@ -269,8 +269,7 @@
proto.write(TrackedJob.SOURCE_UID, jobStatus.getSourceUid());
proto.write(TrackedJob.SOURCE_PACKAGE_NAME, jobStatus.getSourcePackageName());
proto.write(TrackedJob.ARE_CONSTRAINTS_SATISFIED,
- (jobStatus.satisfiedConstraints &
- JobStatus.CONSTRAINT_DEVICE_NOT_DOZING) != 0);
+ (jobStatus.satisfiedConstraints & JobStatus.CONSTRAINT_DEVICE_NOT_DOZING) != 0);
proto.write(TrackedJob.IS_DOZE_WHITELISTED, jobStatus.dozeWhitelisted);
proto.write(TrackedJob.IS_ALLOWED_IN_DOZE, mAllowInIdleJobs.contains(jobStatus));
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/IdleController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/IdleController.java
index e3c311f..d355715 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/IdleController.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/IdleController.java
@@ -20,7 +20,6 @@
import android.content.pm.PackageManager;
import android.os.UserHandle;
import android.util.ArraySet;
-import android.util.Slog;
import android.util.proto.ProtoOutputStream;
import com.android.internal.util.IndentingPrintWriter;
@@ -120,6 +119,7 @@
final long mToken = proto.start(StateControllerProto.IDLE);
proto.write(StateControllerProto.IdleController.IS_IDLE, mIdleTracker.isIdle());
+ mIdleTracker.dump(proto, StateControllerProto.IdleController.IDLENESS_TRACKER);
for (int i = 0; i < mTrackedTasks.size(); i++) {
final JobStatus js = mTrackedTasks.valueAt(i);
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java
index ae4abd6..1133f7b 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java
@@ -16,6 +16,7 @@
package com.android.server.job.controllers;
+import static com.android.server.job.JobSchedulerService.ACTIVE_INDEX;
import static com.android.server.job.JobSchedulerService.sElapsedRealtimeClock;
import android.app.AppGlobals;
@@ -698,6 +699,20 @@
return UserHandle.getUserId(callingUid);
}
+ /**
+ * Returns an appropriate standby bucket for the job, taking into account any standby
+ * exemptions.
+ */
+ public int getEffectiveStandbyBucket() {
+ if (uidActive || getJob().isExemptedFromAppStandby()) {
+ // Treat these cases as if they're in the ACTIVE bucket so that they get throttled
+ // like other ACTIVE apps.
+ return ACTIVE_INDEX;
+ }
+ return getStandbyBucket();
+ }
+
+ /** Returns the real standby bucket of the job. */
public int getStandbyBucket() {
return standbyBucket;
}
@@ -1591,11 +1606,14 @@
for (int i=0; i<changedAuthorities.size(); i++) {
pw.print(prefix); pw.print(" "); pw.println(changedAuthorities.valueAt(i));
}
- if (changedUris != null) {
- pw.print(prefix); pw.println("Changed URIs:");
- for (int i=0; i<changedUris.size(); i++) {
- pw.print(prefix); pw.print(" "); pw.println(changedUris.valueAt(i));
- }
+ }
+ if (changedUris != null) {
+ pw.print(prefix);
+ pw.println("Changed URIs:");
+ for (int i = 0; i < changedUris.size(); i++) {
+ pw.print(prefix);
+ pw.print(" ");
+ pw.println(changedUris.valueAt(i));
}
}
if (network != null) {
@@ -1658,7 +1676,6 @@
proto.write(JobStatusDumpProto.SOURCE_UID, getSourceUid());
proto.write(JobStatusDumpProto.SOURCE_USER_ID, getSourceUserId());
proto.write(JobStatusDumpProto.SOURCE_PACKAGE_NAME, getSourcePackageName());
- proto.write(JobStatusDumpProto.INTERNAL_FLAGS, getInternalFlags());
if (full) {
final long jiToken = proto.start(JobStatusDumpProto.JOB_INFO);
@@ -1672,6 +1689,8 @@
proto.write(JobStatusDumpProto.JobInfo.IS_PERSISTED, job.isPersisted());
proto.write(JobStatusDumpProto.JobInfo.PRIORITY, job.getPriority());
proto.write(JobStatusDumpProto.JobInfo.FLAGS, job.getFlags());
+ proto.write(JobStatusDumpProto.INTERNAL_FLAGS, getInternalFlags());
+ // Foreground exemption can be determined from internal flags value.
proto.write(JobStatusDumpProto.JobInfo.REQUIRES_CHARGING, job.isRequireCharging());
proto.write(JobStatusDumpProto.JobInfo.REQUIRES_BATTERY_NOT_LOW, job.isRequireBatteryNotLow());
@@ -1783,6 +1802,8 @@
proto.write(JobStatusDumpProto.ImplicitConstraints.IS_NOT_DOZING, mReadyNotDozing);
proto.write(JobStatusDumpProto.ImplicitConstraints.IS_NOT_RESTRICTED_IN_BG,
mReadyNotRestrictedInBg);
+ // mReadyDeadlineSatisfied isn't an implicit constraint...and can be determined from other
+ // field values.
proto.end(icToken);
if (changedAuthorities != null) {
@@ -1801,12 +1822,12 @@
network.writeToProto(proto, JobStatusDumpProto.NETWORK);
}
- if (pendingWork != null && pendingWork.size() > 0) {
+ if (pendingWork != null) {
for (int i = 0; i < pendingWork.size(); i++) {
dumpJobWorkItem(proto, JobStatusDumpProto.PENDING_WORK, pendingWork.get(i));
}
}
- if (executingWork != null && executingWork.size() > 0) {
+ if (executingWork != null) {
for (int i = 0; i < executingWork.size(); i++) {
dumpJobWorkItem(proto, JobStatusDumpProto.EXECUTING_WORK, executingWork.get(i));
}
@@ -1831,6 +1852,8 @@
proto.write(JobStatusDumpProto.TIME_UNTIL_LATEST_RUNTIME_MS,
latestRunTimeElapsedMillis - elapsedRealtimeMillis);
}
+ proto.write(JobStatusDumpProto.ORIGINAL_LATEST_RUNTIME_ELAPSED,
+ mOriginalLatestRunTimeElapsedMillis);
proto.write(JobStatusDumpProto.NUM_FAILURES, numFailures);
proto.write(JobStatusDumpProto.LAST_SUCCESSFUL_RUN_TIME, mLastSuccessfulRunTime);
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 043cda4..831be0b 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
@@ -608,7 +608,7 @@
final boolean isWithinQuota = isWithinQuotaLocked(jobStatus);
setConstraintSatisfied(jobStatus, isWithinQuota);
if (!isWithinQuota) {
- maybeScheduleStartAlarmLocked(userId, pkgName, getEffectiveStandbyBucket(jobStatus));
+ maybeScheduleStartAlarmLocked(userId, pkgName, jobStatus.getEffectiveStandbyBucket());
}
}
@@ -719,22 +719,9 @@
return getRemainingExecutionTimeLocked(jobStatus);
}
- /**
- * Returns an appropriate standby bucket for the job, taking into account any standby
- * exemptions.
- */
- private int getEffectiveStandbyBucket(@NonNull final JobStatus jobStatus) {
- if (jobStatus.uidActive || jobStatus.getJob().isExemptedFromAppStandby()) {
- // Treat these cases as if they're in the ACTIVE bucket so that they get throttled
- // like other ACTIVE apps.
- return ACTIVE_INDEX;
- }
- return jobStatus.getStandbyBucket();
- }
-
@VisibleForTesting
boolean isWithinQuotaLocked(@NonNull final JobStatus jobStatus) {
- final int standbyBucket = getEffectiveStandbyBucket(jobStatus);
+ final int standbyBucket = jobStatus.getEffectiveStandbyBucket();
// A job is within quota if one of the following is true:
// 1. it was started while the app was in the TOP state
// 2. the app is currently in the foreground
@@ -784,7 +771,7 @@
long getRemainingExecutionTimeLocked(@NonNull final JobStatus jobStatus) {
return getRemainingExecutionTimeLocked(jobStatus.getSourceUserId(),
jobStatus.getSourcePackageName(),
- getEffectiveStandbyBucket(jobStatus));
+ jobStatus.getEffectiveStandbyBucket());
}
@VisibleForTesting
@@ -1258,7 +1245,7 @@
// finish.
changed |= js.setQuotaConstraintSatisfied(true);
} else if (realStandbyBucket != ACTIVE_INDEX
- && realStandbyBucket == getEffectiveStandbyBucket(js)) {
+ && realStandbyBucket == js.getEffectiveStandbyBucket()) {
// An app in the ACTIVE bucket may be out of quota while the job could be in quota
// for some reason. Therefore, avoid setting the real value here and check each job
// individually.
@@ -2563,7 +2550,7 @@
pw.println();
pw.increaseIndent();
- pw.print(JobStatus.bucketName(getEffectiveStandbyBucket(js)));
+ pw.print(JobStatus.bucketName(js.getEffectiveStandbyBucket()));
pw.print(", ");
if (js.isConstraintSatisfied(JobStatus.CONSTRAINT_WITHIN_QUOTA)) {
pw.print("within quota");
@@ -2661,21 +2648,35 @@
mForegroundUids.keyAt(i));
}
+ for (int i = 0; i < mUidToPackageCache.size(); ++i) {
+ final long upToken = proto.start(
+ StateControllerProto.QuotaController.UID_TO_PACKAGE_CACHE);
+
+ final int uid = mUidToPackageCache.keyAt(i);
+ ArraySet<String> packages = mUidToPackageCache.get(uid);
+
+ proto.write(StateControllerProto.QuotaController.UidPackageMapping.UID, uid);
+ for (int j = 0; j < packages.size(); ++j) {
+ proto.write(StateControllerProto.QuotaController.UidPackageMapping.PACKAGE_NAMES,
+ packages.valueAt(j));
+ }
+
+ proto.end(upToken);
+ }
+
mTrackedJobs.forEach((jobs) -> {
for (int j = 0; j < jobs.size(); j++) {
final JobStatus js = jobs.valueAt(j);
if (!predicate.test(js)) {
continue;
}
- final long jsToken = proto.start(
- StateControllerProto.QuotaController.TRACKED_JOBS);
- js.writeToShortProto(proto,
- StateControllerProto.QuotaController.TrackedJob.INFO);
+ final long jsToken = proto.start(StateControllerProto.QuotaController.TRACKED_JOBS);
+ js.writeToShortProto(proto, StateControllerProto.QuotaController.TrackedJob.INFO);
proto.write(StateControllerProto.QuotaController.TrackedJob.SOURCE_UID,
js.getSourceUid());
proto.write(
StateControllerProto.QuotaController.TrackedJob.EFFECTIVE_STANDBY_BUCKET,
- getEffectiveStandbyBucket(js));
+ js.getEffectiveStandbyBucket());
proto.write(StateControllerProto.QuotaController.TrackedJob.IS_TOP_STARTED_JOB,
mTopStartedJobs.contains(js));
proto.write(StateControllerProto.QuotaController.TrackedJob.HAS_QUOTA,
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/idle/CarIdlenessTracker.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/idle/CarIdlenessTracker.java
index 82c33f5..1e5b84d 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/idle/CarIdlenessTracker.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/idle/CarIdlenessTracker.java
@@ -22,9 +22,11 @@
import android.content.IntentFilter;
import android.util.Log;
import android.util.Slog;
+import android.util.proto.ProtoOutputStream;
import com.android.server.am.ActivityManagerService;
import com.android.server.job.JobSchedulerService;
+import com.android.server.job.StateControllerProto;
import java.io.PrintWriter;
@@ -89,6 +91,22 @@
}
@Override
+ public void dump(ProtoOutputStream proto, long fieldId) {
+ final long token = proto.start(fieldId);
+ final long ciToken = proto.start(
+ StateControllerProto.IdleController.IdlenessTracker.CAR_IDLENESS_TRACKER);
+
+ proto.write(StateControllerProto.IdleController.IdlenessTracker.CarIdlenessTracker.IS_IDLE,
+ mIdle);
+ proto.write(
+ StateControllerProto.IdleController.IdlenessTracker.CarIdlenessTracker.IS_GARAGE_MODE_ON,
+ mGarageModeOn);
+
+ proto.end(ciToken);
+ proto.end(token);
+ }
+
+ @Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
logIfDebug("Received action: " + action);
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/idle/DeviceIdlenessTracker.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/idle/DeviceIdlenessTracker.java
index a85bd40..f74eb3b 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/idle/DeviceIdlenessTracker.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/idle/DeviceIdlenessTracker.java
@@ -23,11 +23,13 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
-
import android.util.Log;
import android.util.Slog;
+import android.util.proto.ProtoOutputStream;
+
import com.android.server.am.ActivityManagerService;
import com.android.server.job.JobSchedulerService;
+import com.android.server.job.StateControllerProto;
import java.io.PrintWriter;
@@ -101,6 +103,25 @@
}
@Override
+ public void dump(ProtoOutputStream proto, long fieldId) {
+ final long token = proto.start(fieldId);
+ final long diToken = proto.start(
+ StateControllerProto.IdleController.IdlenessTracker.DEVICE_IDLENESS_TRACKER);
+
+ proto.write(StateControllerProto.IdleController.IdlenessTracker.DeviceIdlenessTracker.IS_IDLE,
+ mIdle);
+ proto.write(
+ StateControllerProto.IdleController.IdlenessTracker.DeviceIdlenessTracker.IS_SCREEN_ON,
+ mScreenOn);
+ proto.write(
+ StateControllerProto.IdleController.IdlenessTracker.DeviceIdlenessTracker.IS_DOCK_IDLE,
+ mDockIdle);
+
+ proto.end(diToken);
+ proto.end(token);
+ }
+
+ @Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
if (action.equals(Intent.ACTION_SCREEN_ON)
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/idle/IdlenessTracker.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/idle/IdlenessTracker.java
index 09f01c2..cdab7e5 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/idle/IdlenessTracker.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/idle/IdlenessTracker.java
@@ -17,6 +17,7 @@
package com.android.server.job.controllers.idle;
import android.content.Context;
+import android.util.proto.ProtoOutputStream;
import java.io.PrintWriter;
@@ -43,4 +44,9 @@
* Dump useful information about tracked idleness-related state in plaintext.
*/
void dump(PrintWriter pw);
+
+ /**
+ * Dump useful information about tracked idleness-related state to proto.
+ */
+ void dump(ProtoOutputStream proto, long fieldId);
}
diff --git a/api/current.txt b/api/current.txt
index fe78138..e11fca8 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -641,6 +641,7 @@
field public static final int footerDividersEnabled = 16843311; // 0x101022f
field public static final int forceDarkAllowed = 16844172; // 0x101058c
field public static final int forceHasOverlappingRendering = 16844065; // 0x1010521
+ field public static final int forceQueryable = 16844296; // 0x1010608
field public static final int forceUriPermissions = 16844191; // 0x101059f
field public static final int foreground = 16843017; // 0x1010109
field public static final int foregroundGravity = 16843264; // 0x1010200
@@ -9479,47 +9480,62 @@
}
public class ContentProviderOperation implements android.os.Parcelable {
- method public android.content.ContentProviderResult apply(android.content.ContentProvider, android.content.ContentProviderResult[], int) throws android.content.OperationApplicationException;
+ method @NonNull public android.content.ContentProviderResult apply(@NonNull android.content.ContentProvider, @NonNull android.content.ContentProviderResult[], int) throws android.content.OperationApplicationException;
method public int describeContents();
- method public android.net.Uri getUri();
+ method @NonNull public android.net.Uri getUri();
method public boolean isAssertQuery();
+ method public boolean isCall();
method public boolean isDelete();
+ method public boolean isExceptionAllowed();
method public boolean isInsert();
method public boolean isReadOperation();
method public boolean isUpdate();
method public boolean isWriteOperation();
method public boolean isYieldAllowed();
- method public static android.content.ContentProviderOperation.Builder newAssertQuery(android.net.Uri);
- method public static android.content.ContentProviderOperation.Builder newDelete(android.net.Uri);
- method public static android.content.ContentProviderOperation.Builder newInsert(android.net.Uri);
- method public static android.content.ContentProviderOperation.Builder newUpdate(android.net.Uri);
- method public String[] resolveSelectionArgsBackReferences(android.content.ContentProviderResult[], int);
- method public android.content.ContentValues resolveValueBackReferences(android.content.ContentProviderResult[], int);
+ method @NonNull public static android.content.ContentProviderOperation.Builder newAssertQuery(@NonNull android.net.Uri);
+ method @NonNull public static android.content.ContentProviderOperation.Builder newCall(@NonNull android.net.Uri, @Nullable String, @Nullable String);
+ method @NonNull public static android.content.ContentProviderOperation.Builder newDelete(@NonNull android.net.Uri);
+ method @NonNull public static android.content.ContentProviderOperation.Builder newInsert(@NonNull android.net.Uri);
+ method @NonNull public static android.content.ContentProviderOperation.Builder newUpdate(@NonNull android.net.Uri);
+ method @Nullable public android.os.Bundle resolveExtrasBackReferences(@NonNull android.content.ContentProviderResult[], int);
+ method @Nullable public String[] resolveSelectionArgsBackReferences(@NonNull android.content.ContentProviderResult[], int);
+ method @Nullable public android.content.ContentValues resolveValueBackReferences(@NonNull android.content.ContentProviderResult[], int);
method public void writeToParcel(android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.content.ContentProviderOperation> CREATOR;
}
public static class ContentProviderOperation.Builder {
- method public android.content.ContentProviderOperation build();
- method public android.content.ContentProviderOperation.Builder withExpectedCount(int);
- method public android.content.ContentProviderOperation.Builder withSelection(String, String[]);
- method public android.content.ContentProviderOperation.Builder withSelectionBackReference(int, int);
- method public android.content.ContentProviderOperation.Builder withValue(String, Object);
- method public android.content.ContentProviderOperation.Builder withValueBackReference(String, int);
- method public android.content.ContentProviderOperation.Builder withValueBackReferences(android.content.ContentValues);
- method public android.content.ContentProviderOperation.Builder withValues(android.content.ContentValues);
- method public android.content.ContentProviderOperation.Builder withYieldAllowed(boolean);
+ method @NonNull public android.content.ContentProviderOperation build();
+ method @NonNull public android.content.ContentProviderOperation.Builder withExceptionAllowed(boolean);
+ method @NonNull public android.content.ContentProviderOperation.Builder withExpectedCount(int);
+ method @NonNull public android.content.ContentProviderOperation.Builder withExtra(@NonNull String, @Nullable Object);
+ method @NonNull public android.content.ContentProviderOperation.Builder withExtraBackReference(@NonNull String, int);
+ method @NonNull public android.content.ContentProviderOperation.Builder withExtraBackReference(@NonNull String, int, @NonNull String);
+ method @NonNull public android.content.ContentProviderOperation.Builder withExtras(@NonNull android.os.Bundle);
+ method @NonNull public android.content.ContentProviderOperation.Builder withSelection(@Nullable String, @Nullable String[]);
+ method @NonNull public android.content.ContentProviderOperation.Builder withSelectionBackReference(int, int);
+ method @NonNull public android.content.ContentProviderOperation.Builder withSelectionBackReference(int, int, @NonNull String);
+ method @NonNull public android.content.ContentProviderOperation.Builder withValue(@NonNull String, @Nullable Object);
+ method @NonNull public android.content.ContentProviderOperation.Builder withValueBackReference(@NonNull String, int);
+ method @NonNull public android.content.ContentProviderOperation.Builder withValueBackReference(@NonNull String, int, @NonNull String);
+ method @NonNull public android.content.ContentProviderOperation.Builder withValueBackReferences(@NonNull android.content.ContentValues);
+ method @NonNull public android.content.ContentProviderOperation.Builder withValues(@NonNull android.content.ContentValues);
+ method @NonNull public android.content.ContentProviderOperation.Builder withYieldAllowed(boolean);
}
public class ContentProviderResult implements android.os.Parcelable {
- ctor public ContentProviderResult(android.net.Uri);
+ ctor public ContentProviderResult(@NonNull android.net.Uri);
ctor public ContentProviderResult(int);
+ ctor public ContentProviderResult(@NonNull android.os.Bundle);
+ ctor public ContentProviderResult(@NonNull Exception);
ctor public ContentProviderResult(android.os.Parcel);
method public int describeContents();
method public void writeToParcel(android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.content.ContentProviderResult> CREATOR;
- field public final Integer count;
- field public final android.net.Uri uri;
+ field @Nullable public final Integer count;
+ field @Nullable public final Exception exception;
+ field @Nullable public final android.os.Bundle extras;
+ field @Nullable public final android.net.Uri uri;
}
public class ContentQueryMap extends java.util.Observable {
@@ -40629,8 +40645,9 @@
package android.security {
public final class AttestedKeyPair {
- method public java.util.List<java.security.cert.Certificate> getAttestationRecord();
- method public java.security.KeyPair getKeyPair();
+ ctor public AttestedKeyPair(@Nullable java.security.KeyPair, @Nullable java.security.cert.Certificate[]);
+ method @NonNull public java.util.List<java.security.cert.Certificate> getAttestationRecord();
+ method @Nullable public java.security.KeyPair getKeyPair();
}
public class ConfirmationAlreadyPresentingException extends java.lang.Exception {
@@ -73167,7 +73184,7 @@
method public void logp(@NonNull java.util.logging.Level, @Nullable String, @Nullable String, @Nullable String);
method public void logp(@NonNull java.util.logging.Level, @Nullable String, @Nullable String, @NonNull java.util.function.Supplier<java.lang.String>);
method public void logp(@NonNull java.util.logging.Level, @Nullable String, @Nullable String, @Nullable String, @Nullable Object);
- method public void logp(@NonNull java.util.logging.Level, @Nullable String, @Nullable String, @Nullable String, Object[]);
+ method public void logp(@NonNull java.util.logging.Level, @Nullable String, @Nullable String, @Nullable String, @Nullable Object[]);
method public void logp(@NonNull java.util.logging.Level, @Nullable String, @Nullable String, @Nullable String, @Nullable Throwable);
method public void logp(@NonNull java.util.logging.Level, @Nullable String, @Nullable String, @Nullable Throwable, @NonNull java.util.function.Supplier<java.lang.String>);
method @Deprecated public void logrb(@NonNull java.util.logging.Level, @Nullable String, @Nullable String, @Nullable String, @Nullable String);
diff --git a/api/removed.txt b/api/removed.txt
index b075f9e..74c1d3c 100644
--- a/api/removed.txt
+++ b/api/removed.txt
@@ -208,7 +208,7 @@
package android.icu.util {
public class JapaneseCalendar extends android.icu.util.GregorianCalendar {
- field public static final int CURRENT_ERA;
+ field @Deprecated public static final int CURRENT_ERA;
}
}
diff --git a/api/system-current.txt b/api/system-current.txt
index b4e6554..76d017c 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -3693,7 +3693,7 @@
package android.media.session {
public final class MediaSessionManager {
- method @RequiresPermission(android.Manifest.permission.MEDIA_CONTENT_CONTROL) public void registerCallback(@NonNull android.media.session.MediaSessionManager.Callback, @Nullable android.os.Handler);
+ method @RequiresPermission(android.Manifest.permission.MEDIA_CONTENT_CONTROL) public void registerCallback(@NonNull java.util.concurrent.Executor, @NonNull android.media.session.MediaSessionManager.Callback);
method @RequiresPermission(android.Manifest.permission.SET_MEDIA_KEY_LISTENER) public void setOnMediaKeyListener(android.media.session.MediaSessionManager.OnMediaKeyListener, @Nullable android.os.Handler);
method @RequiresPermission(android.Manifest.permission.SET_VOLUME_KEY_LONG_PRESS_LISTENER) public void setOnVolumeKeyLongPressListener(android.media.session.MediaSessionManager.OnVolumeKeyLongPressListener, @Nullable android.os.Handler);
method @RequiresPermission(android.Manifest.permission.MEDIA_CONTENT_CONTROL) public void unregisterCallback(@NonNull android.media.session.MediaSessionManager.Callback);
@@ -6286,6 +6286,7 @@
package android.service.autofill {
public abstract class AutofillFieldClassificationService extends android.app.Service {
+ ctor public AutofillFieldClassificationService();
method public android.os.IBinder onBind(android.content.Intent);
method @Nullable public float[][] onCalculateScores(@NonNull java.util.List<android.view.autofill.AutofillValue>, @NonNull java.util.List<java.lang.String>, @NonNull java.util.List<java.lang.String>, @Nullable String, @Nullable android.os.Bundle, @Nullable java.util.Map, @Nullable java.util.Map);
method @Deprecated @Nullable public float[][] onGetScores(@Nullable String, @Nullable android.os.Bundle, @NonNull java.util.List<android.view.autofill.AutofillValue>, @NonNull java.util.List<java.lang.String>);
diff --git a/api/test-current.txt b/api/test-current.txt
index 46a0e1b..e9615111 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -2348,6 +2348,7 @@
method public static android.net.Uri scanFile(android.content.Context, java.io.File);
method public static android.net.Uri scanFileFromShell(android.content.Context, java.io.File);
method public static void scanVolume(android.content.Context, java.io.File);
+ method public static void waitForIdle(android.content.Context);
}
public final class Settings {
@@ -2464,6 +2465,7 @@
package android.service.autofill {
public abstract class AutofillFieldClassificationService extends android.app.Service {
+ ctor public AutofillFieldClassificationService();
method public android.os.IBinder onBind(android.content.Intent);
field public static final String REQUIRED_ALGORITHM_EDIT_DISTANCE = "EDIT_DISTANCE";
field public static final String REQUIRED_ALGORITHM_EXACT_MATCH = "EXACT_MATCH";
@@ -3042,6 +3044,7 @@
field public static final String SCREENRECORD_LONG_PRESS = "settings_screenrecord_long_press";
field public static final String SEAMLESS_TRANSFER = "settings_seamless_transfer";
field public static final String SETTINGS_WIFITRACKER2 = "settings_wifitracker2";
+ field public static final String USE_BUGREPORT_API = "settings_use_bugreport_api";
}
public class TimeUtils {
diff --git a/cmds/idmap/scan.cpp b/cmds/idmap/scan.cpp
index d69dd79..847dda3 100644
--- a/cmds/idmap/scan.cpp
+++ b/cmds/idmap/scan.cpp
@@ -9,7 +9,6 @@
#include <androidfw/ResourceTypes.h>
#include <androidfw/StreamingZipInflater.h>
#include <androidfw/ZipFileRO.h>
-#include <cutils/jstring.h>
#include <cutils/properties.h>
#include <private/android_filesystem_config.h> // for AID_SYSTEM
#include <utils/SortedVector.h>
@@ -84,15 +83,9 @@
}
bool check_property(String16 property, String16 value) {
- const char *prop;
- const char *val;
-
- prop = strndup16to8(property.string(), property.size());
char propBuf[PROPERTY_VALUE_MAX];
- property_get(prop, propBuf, NULL);
- val = strndup16to8(value.string(), value.size());
-
- return (strcmp(propBuf, val) == 0);
+ property_get(String8(property).c_str(), propBuf, NULL);
+ return String8(value) == propBuf;
}
int parse_overlay_tag(const ResXMLTree& parser, const char *target_package_name,
diff --git a/config/boot-profile.txt b/config/boot-profile.txt
index 57e06c2..e0e9164 100644
--- a/config/boot-profile.txt
+++ b/config/boot-profile.txt
@@ -1,642 +1,1221 @@
-Lcom/android/internal/os/RuntimeInit$MethodAndArgsCaller;->run()V
-Lcom/android/internal/os/ZygoteInit;->main([Ljava/lang/String;)V
-Lcom/android/internal/util/ConcurrentUtils$1$1;->run()V
-Lcom/android/server/SystemConfig;->getInstance()Lcom/android/server/SystemConfig;
-Lcom/android/server/SystemConfig;-><init>()V
-Lcom/android/server/SystemConfig;->readPermissions(Ljava/io/File;I)V
-Lcom/android/server/SystemConfig;->readPermissionsFromXml(Ljava/io/File;I)V
-Lcom/android/internal/os/ProcessCpuTracker;->update()V
-Lcom/android/internal/os/ProcessCpuTracker;->init()V
-Lcom/android/internal/os/ProcessCpuTracker;->collectStats(Ljava/lang/String;IZ[ILjava/util/ArrayList;)[I
-Landroid/content/pm/PackageParser$SigningDetails$Builder;->build()Landroid/content/pm/PackageParser$SigningDetails;
-Landroid/content/pm/PackageParser$SigningDetails;-><init>(Landroid/content/pm/PackageParser$SigningDetails;)V
-Landroid/content/pm/PackageParser$SigningDetails;-><init>([Landroid/content/pm/Signature;I)V
-Landroid/content/pm/PackageParser$SigningDetails;-><init>([Landroid/content/pm/Signature;ILandroid/util/ArraySet;[Landroid/content/pm/Signature;)V
-Landroid/content/pm/PackageParser$SigningDetails;-><init>([Landroid/content/pm/Signature;I[Landroid/content/pm/Signature;)V
+Landroid/os/Trace;->isTagEnabled(J)Z
+Lcom/android/internal/os/ZygoteInit;->preloadClasses()V
+Landroid/os/Trace;->traceBegin(JLjava/lang/String;)V
+Landroid/os/Trace;->traceEnd(J)V
+Landroid/graphics/FontListParser;->readFamily(Lorg/xmlpull/v1/XmlPullParser;Ljava/lang/String;)Landroid/text/FontConfig$Family;
+Landroid/graphics/FontListParser;->readFont(Lorg/xmlpull/v1/XmlPullParser;Ljava/lang/String;)Landroid/text/FontConfig$Font;
+Landroid/graphics/FontListParser;->readFamilies(Lorg/xmlpull/v1/XmlPullParser;Ljava/lang/String;)Landroid/text/FontConfig;
+Landroid/text/FontConfig$Font;-><init>(Ljava/lang/String;I[Landroid/graphics/fonts/FontVariationAxis;IZLjava/lang/String;)V
+Landroid/util/ContainerHelpers;->binarySearch([III)I
+Landroid/graphics/fonts/SystemFonts;->pushFamilyToFallback(Landroid/text/FontConfig$Family;Landroid/util/ArrayMap;Ljava/util/Map;Ljava/util/ArrayList;)V
+Landroid/util/ArrayMap;->indexOf(Ljava/lang/Object;I)I
+Lcom/android/internal/util/Preconditions;->checkArgument(ZLjava/lang/Object;)V
+Lcom/android/internal/util/Preconditions;->checkNotNull(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
+Landroid/graphics/fonts/Font;->getStyle()Landroid/graphics/fonts/FontStyle;
Landroid/util/ArrayMap;->get(Ljava/lang/Object;)Ljava/lang/Object;
Landroid/util/ArrayMap;->indexOfKey(Ljava/lang/Object;)I
-Landroid/content/pm/Signature;->getPublicKey()Ljava/security/PublicKey;
-Landroid/util/ArrayMap;->indexOf(Ljava/lang/Object;I)I
-Landroid/util/ArrayMap;->indexOfNull()I
-Landroid/util/ArrayMap;->indexOfValue(Ljava/lang/Object;)I
-Lcom/android/internal/os/ProcessCpuTracker;->getName(Lcom/android/internal/os/ProcessCpuTracker$Stats;Ljava/lang/String;)V
-Lcom/android/internal/os/ProcStatsUtil;->readTerminatedProcFile(Ljava/lang/String;B)Ljava/lang/String;
-Lcom/android/internal/os/BatteryStatsImpl;->writeAsyncLocked()V
-Lcom/android/internal/os/BatteryStatsImpl;->writeStatsLocked(Z)V
-Lcom/android/internal/os/BatteryStatsImpl;->writeSummaryToParcel(Landroid/os/Parcel;Z)V
-Landroid/util/SparseArray;->get(I)Ljava/lang/Object;
-Landroid/util/SparseArray;->get(ILjava/lang/Object;)Ljava/lang/Object;
-Lcom/android/internal/os/BatteryStatsImpl;->readLocked()V
-Lcom/android/internal/os/BatteryStatsImpl;->readSummaryFromParcel(Landroid/os/Parcel;)V
-Landroid/util/ArrayMap;->binarySearchHashes([III)I
-Landroid/util/ContainerHelpers;->binarySearch([III)I
-Lcom/android/internal/os/BatteryStatsImpl;->updateCpuTimeLocked(ZZ)V
-Lcom/android/internal/os/KernelCpuUidTimeReader;->readDelta(Lcom/android/internal/os/KernelCpuUidTimeReader$Callback;)V
-Landroid/util/ArrayMap;->put(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-Landroid/util/ArrayMap;->putAll(Landroid/util/ArrayMap;)V
-Landroid/util/ArrayMap;->putAll(Ljava/util/Map;)V
-Landroid/util/SparseArray;-><init>()V
-Landroid/util/SparseArray;-><init>(I)V
-Lcom/android/internal/os/KernelCpuUidTimeReader$KernelCpuUidFreqTimeReader;->readDeltaImpl(Lcom/android/internal/os/KernelCpuUidTimeReader$Callback;)V
-Lcom/android/server/SystemConfig;->readPrivAppPermissions(Lorg/xmlpull/v1/XmlPullParser;Landroid/util/ArrayMap;Landroid/util/ArrayMap;)V
-Landroid/content/pm/Signature;-><init>(Ljava/lang/String;)V
-Landroid/content/pm/Signature;-><init>([B)V
-Landroid/content/pm/Signature;-><init>([Ljava/security/cert/Certificate;)V
-Lcom/android/internal/os/ProcessCpuTracker$Stats;-><init>(IIZ)V
-Lcom/android/internal/os/KernelCpuProcStringReader;->asLongs(Ljava/nio/CharBuffer;[J)I
-Lcom/android/internal/util/XmlUtils;->nextElement(Lorg/xmlpull/v1/XmlPullParser;)V
-Lcom/android/internal/util/XmlUtils;->nextElementWithin(Lorg/xmlpull/v1/XmlPullParser;I)Z
-Lcom/android/internal/util/ArrayUtils;->newUnpaddedObjectArray(I)[Ljava/lang/Object;
-Landroid/util/SparseArray;->put(ILjava/lang/Object;)V
-Lcom/android/internal/os/BatteryStatsImpl;->updateKernelWakelocksLocked()V
-Landroid/util/ArraySet;->add(Ljava/lang/Object;)Z
-Landroid/util/ArraySet;->addAll(Landroid/util/ArraySet;)V
-Landroid/util/ArraySet;->addAll(Ljava/util/Collection;)Z
-Lcom/android/internal/os/KernelWakelockReader;->readKernelWakelockStats(Lcom/android/internal/os/KernelWakelockStats;)Lcom/android/internal/os/KernelWakelockStats;
-Lcom/android/internal/util/GrowingArrayUtils;->insert([IIII)[I
-Lcom/android/internal/util/GrowingArrayUtils;->insert([JIIJ)[J
-Lcom/android/internal/util/GrowingArrayUtils;->insert([Ljava/lang/Object;IILjava/lang/Object;)[Ljava/lang/Object;
-Lcom/android/internal/util/GrowingArrayUtils;->insert([ZIIZ)[Z
-HPLcom/android/internal/app/procstats/ProcessStats;-><init>(Landroid/os/Parcel;)V
-Lcom/android/internal/app/procstats/ProcessStats;-><init>(Z)V
-Lcom/android/internal/os/BatteryStatsImpl$Uid;-><init>(Lcom/android/internal/os/BatteryStatsImpl;I)V
-Lcom/android/internal/os/KernelWakelockReader;->parseProcWakelocks([BIZLcom/android/internal/os/KernelWakelockStats;)Lcom/android/internal/os/KernelWakelockStats;
-Landroid/content/pm/PackageParser;->getCachedResult(Ljava/io/File;I)Landroid/content/pm/PackageParser$Package;
-Landroid/content/pm/PackageParser;->parsePackage(Ljava/io/File;I)Landroid/content/pm/PackageParser$Package;
-Landroid/content/pm/PackageParser;->parsePackage(Ljava/io/File;IZ)Landroid/content/pm/PackageParser$Package;
-Landroid/content/pm/PackageParser;->parsePackageItemInfo(Landroid/content/pm/PackageParser$Package;Landroid/content/pm/PackageItemInfo;[Ljava/lang/String;Ljava/lang/String;Landroid/content/res/TypedArray;ZIIIIII)Z
-Landroid/content/pm/PackageParser;->parsePackageList(Ljava/lang/String;)Ljava/util/Set;
-Landroid/content/pm/PackageParser;->parsePackageLite(Ljava/io/File;I)Landroid/content/pm/PackageParser$PackageLite;
-Landroid/content/pm/PackageParser;->parsePackageSplitNames(Lorg/xmlpull/v1/XmlPullParser;Landroid/util/AttributeSet;)Landroid/util/Pair;
-Lcom/android/internal/os/BatteryStatsImpl$DualTimer;->writeSummaryFromParcelLocked(Landroid/os/Parcel;J)V
-Landroid/content/pm/Signature;->parseHexDigit(I)I
-Lcom/android/internal/os/BatteryStatsImpl$DurationTimer;->writeSummaryFromParcelLocked(Landroid/os/Parcel;J)V
-Lcom/android/internal/os/BatteryStatsImpl$Uid;->readWakeSummaryFromParcelLocked(Ljava/lang/String;Landroid/os/Parcel;)V
-Landroid/util/ArraySet;->iterator()Ljava/util/Iterator;
-Landroid/content/pm/PackageParser;->fromCacheEntryStatic([B)Landroid/content/pm/PackageParser$Package;
-Landroid/content/pm/PackageParser;->fromCacheEntry([B)Landroid/content/pm/PackageParser$Package;
-Lcom/android/internal/os/BatteryStatsImpl$Timer;->writeSummaryFromParcelLocked(Landroid/os/Parcel;J)V
-Lcom/android/internal/os/KernelCpuUidTimeReader$KernelCpuUidUserSysTimeReader;->readDeltaImpl(Lcom/android/internal/os/KernelCpuUidTimeReader$Callback;)V
-Landroid/os/FileUtils;->bytesToFile(Ljava/lang/String;[B)V
-Landroid/os/StrictMode;->allowThreadDiskReads()Landroid/os/StrictMode$ThreadPolicy;
-Landroid/os/StrictMode;->allowThreadDiskReadsMask()I
-Landroid/content/pm/PackageParser$Package;-><init>(Landroid/os/Parcel;)V
-Landroid/content/pm/PackageParser$Package;-><init>(Ljava/lang/String;)V
-Lcom/android/server/SystemConfig;->addFeature(Ljava/lang/String;I)V
-Landroid/os/StrictMode;->setThreadPolicy(Landroid/os/StrictMode$ThreadPolicy;)V
-Landroid/os/StrictMode;->setThreadPolicyMask(I)V
-Landroid/content/pm/FallbackCategoryProvider;->loadFallbacks()V
-Landroid/os/Parcel$ReadWriteHelper;->writeString(Landroid/os/Parcel;Ljava/lang/String;)V
-Landroid/os/Parcel;->writeString(Ljava/lang/String;)V
-Landroid/os/Parcel;->writeStringArray([Ljava/lang/String;)V
-Landroid/os/Parcel;->writeStringList(Ljava/util/List;)V
-Lcom/android/internal/os/BatteryStatsImpl$Timer;-><init>(Lcom/android/internal/os/BatteryStatsImpl$Clocks;ILcom/android/internal/os/BatteryStatsImpl$TimeBase;)V
-Lcom/android/internal/os/BatteryStatsImpl$Timer;-><init>(Lcom/android/internal/os/BatteryStatsImpl$Clocks;ILcom/android/internal/os/BatteryStatsImpl$TimeBase;Landroid/os/Parcel;)V
-Lcom/android/internal/os/BatteryStatsImpl$TimeBase;->add(Lcom/android/internal/os/BatteryStatsImpl$TimeBaseObs;)V
-Landroid/os/Parcel;->writeInt(I)V
-Landroid/os/Parcel;->writeIntArray([I)V
-Landroid/os/Parcel;->writeInterfaceToken(Ljava/lang/String;)V
-Landroid/content/pm/PackageParser;->parsePublicKey(Ljava/lang/String;)Ljava/security/PublicKey;
-Lcom/android/internal/os/KernelCpuProcStringReader$ProcFileIterator;->nextLine()Ljava/nio/CharBuffer;
-Landroid/util/Xml;->newPullParser()Lorg/xmlpull/v1/XmlPullParser;
-Lcom/android/internal/os/KernelCpuUidTimeReader$KernelCpuUidFreqTimeReader;->readFreqs(Lcom/android/internal/os/PowerProfile;)[J
-Lcom/android/internal/os/KernelCpuUidTimeReader$KernelCpuUidFreqTimeReader;->readFreqs(Ljava/lang/String;)[J
-Lcom/android/internal/os/BatteryStatsImpl$StopwatchTimer;-><init>(Lcom/android/internal/os/BatteryStatsImpl$Clocks;Lcom/android/internal/os/BatteryStatsImpl$Uid;ILjava/util/ArrayList;Lcom/android/internal/os/BatteryStatsImpl$TimeBase;)V
-Lcom/android/internal/os/BatteryStatsImpl$StopwatchTimer;-><init>(Lcom/android/internal/os/BatteryStatsImpl$Clocks;Lcom/android/internal/os/BatteryStatsImpl$Uid;ILjava/util/ArrayList;Lcom/android/internal/os/BatteryStatsImpl$TimeBase;Landroid/os/Parcel;)V
-Landroid/os/HandlerThread;->run()V
-Landroid/os/Looper;->loop()V
-Landroid/util/SparseArray;->size()I
-Landroid/util/ArrayMap;-><init>()V
-Landroid/util/ArrayMap;-><init>(I)V
-Landroid/util/ArrayMap;-><init>(IZ)V
-Landroid/util/ArrayMap;-><init>(Landroid/util/ArrayMap;)V
-Landroid/os/Parcel;->writeLong(J)V
-Landroid/os/Parcel;->writeLongArray([J)V
-Landroid/os/Parcel;->readParcelable(Ljava/lang/ClassLoader;)Landroid/os/Parcelable;
-Landroid/os/Parcel;->readParcelableArray(Ljava/lang/ClassLoader;Ljava/lang/Class;)[Landroid/os/Parcelable;
-Landroid/os/Parcel;->readParcelableCreator(Ljava/lang/ClassLoader;)Landroid/os/Parcelable$Creator;
-Landroid/os/Parcel;->readParcelableList(Ljava/util/List;Ljava/lang/ClassLoader;)Ljava/util/List;
-Lcom/android/internal/os/BatteryStatsImpl$DualTimer;-><init>(Lcom/android/internal/os/BatteryStatsImpl$Clocks;Lcom/android/internal/os/BatteryStatsImpl$Uid;ILjava/util/ArrayList;Lcom/android/internal/os/BatteryStatsImpl$TimeBase;Lcom/android/internal/os/BatteryStatsImpl$TimeBase;Landroid/os/Parcel;)V
-Landroid/os/SystemProperties;->getBoolean(Ljava/lang/String;Z)Z
-Landroid/content/pm/IntentFilterVerificationInfo;-><init>(Lorg/xmlpull/v1/XmlPullParser;)V
-Landroid/util/ArrayMap;->allocArrays(I)V
-Landroid/os/Parcel;->readInt()I
-Landroid/os/Parcel;->readIntArray([I)V
-Landroid/content/pm/IntentFilterVerificationInfo;->readFromXml(Lorg/xmlpull/v1/XmlPullParser;)V
-Lcom/android/internal/util/ArrayUtils;->appendInt([II)[I
-Lcom/android/internal/util/ArrayUtils;->appendInt([IIZ)[I
-Landroid/util/TimingsTraceLog;->traceEnd()V
-Lcom/android/internal/os/BatteryStatsImpl$Timer;->readSummaryFromParcelLocked(Landroid/os/Parcel;)V
-Lcom/android/internal/os/BatteryStatsImpl$DurationTimer;->readSummaryFromParcelLocked(Landroid/os/Parcel;)V
-Landroid/os/Parcel;->readString()Ljava/lang/String;
-Landroid/os/Parcel;->readStringArray()[Ljava/lang/String;
-Landroid/os/Parcel;->readStringList(Ljava/util/List;)V
-Lcom/android/internal/os/BatteryStatsImpl$OverflowArrayMap;->add(Ljava/lang/String;Ljava/lang/Object;)V
-Lcom/android/internal/os/BatteryStatsImpl;->getKernelWakelockTimerLocked(Ljava/lang/String;)Lcom/android/internal/os/BatteryStatsImpl$SamplingTimer;
-Lcom/android/internal/os/BatteryStatsImpl$DurationTimer;-><init>(Lcom/android/internal/os/BatteryStatsImpl$Clocks;Lcom/android/internal/os/BatteryStatsImpl$Uid;ILjava/util/ArrayList;Lcom/android/internal/os/BatteryStatsImpl$TimeBase;Landroid/os/Parcel;)V
-Lcom/android/internal/os/BatteryStatsImpl$DualTimer;->readSummaryFromParcelLocked(Landroid/os/Parcel;)V
-Landroid/os/storage/StorageManager;->hasAdoptable()Z
-Landroid/os/Parcel$ReadWriteHelper;->readString(Landroid/os/Parcel;)Ljava/lang/String;
-Landroid/os/Handler;->dispatchMessage(Landroid/os/Message;)V
-Lcom/android/internal/os/BatteryStatsImpl$5;->run()V
-Lcom/android/internal/os/BatteryStatsImpl;->commitPendingDataToDisk(Landroid/os/Parcel;Lcom/android/internal/os/AtomicFile;)V
-Lcom/android/internal/os/BatteryStatsImpl$StopwatchTimer;->readSummaryFromParcelLocked(Landroid/os/Parcel;)V
-Landroid/util/ArraySet;->indexOf(Ljava/lang/Object;)I
-Landroid/util/ArraySet;->indexOf(Ljava/lang/Object;I)I
-Landroid/util/ArraySet;->indexOfNull()I
-Landroid/os/Parcel;->readLong()J
-Landroid/os/Parcel;->readLongArray([J)V
-Lcom/android/internal/util/XmlUtils;->skipCurrentTag(Lorg/xmlpull/v1/XmlPullParser;)V
-Lcom/android/internal/os/BatteryStatsImpl$Uid;->getServiceStatsLocked(Ljava/lang/String;Ljava/lang/String;)Lcom/android/internal/os/BatteryStatsImpl$Uid$Pkg$Serv;
-Landroid/os/StrictMode;->setBlockGuardPolicy(I)V
-Landroid/util/TimingsTraceLog;->logDuration(Ljava/lang/String;J)V
-Landroid/util/Base64;->decode(Ljava/lang/String;I)[B
-Landroid/util/Base64;->decode([BI)[B
-Landroid/util/Base64;->decode([BIII)[B
-Landroid/util/ArrayMap;->valueAt(I)Ljava/lang/Object;
-Lcom/android/internal/os/BatteryStatsImpl$Uid;->getWakelockTimerLocked(Lcom/android/internal/os/BatteryStatsImpl$Uid$Wakelock;I)Lcom/android/internal/os/BatteryStatsImpl$StopwatchTimer;
-Landroid/util/ArraySet;-><init>()V
-Landroid/util/ArraySet;-><init>(I)V
-Landroid/util/ArraySet;-><init>(Landroid/util/ArraySet;)V
-Landroid/util/ArraySet;-><init>(Ljava/util/Collection;)V
-Lcom/android/internal/os/KernelCpuProcStringReader;->open(Z)Lcom/android/internal/os/KernelCpuProcStringReader$ProcFileIterator;
-Landroid/content/pm/ApplicationInfo;-><init>()V
-Landroid/content/pm/ApplicationInfo;-><init>(Landroid/content/pm/ApplicationInfo;)V
-Landroid/content/pm/ApplicationInfo;-><init>(Landroid/os/Parcel;)V
-Landroid/util/ArraySet;->remove(Ljava/lang/Object;)Z
-Landroid/util/ArraySet;->removeAll(Ljava/util/Collection;)Z
-Landroid/util/ArraySet;->removeAt(I)Ljava/lang/Object;
-Landroid/util/ArraySet;->removeAll(Landroid/util/ArraySet;)Z
-Landroid/content/pm/ApplicationInfo$1;->createFromParcel(Landroid/os/Parcel;)Landroid/content/pm/ApplicationInfo;
-Landroid/content/pm/ApplicationInfo$1;->createFromParcel(Landroid/os/Parcel;)Ljava/lang/Object;
-Landroid/os/ServiceManagerProxy;->addService(Ljava/lang/String;Landroid/os/IBinder;ZI)V
-Lcom/android/internal/os/PowerProfile;-><init>(Landroid/content/Context;)V
-Lcom/android/internal/os/PowerProfile;-><init>(Landroid/content/Context;Z)V
-Lcom/android/internal/os/BatteryStatsImpl$SamplingTimer;-><init>(Lcom/android/internal/os/BatteryStatsImpl$Clocks;Lcom/android/internal/os/BatteryStatsImpl$TimeBase;Landroid/os/Parcel;)V
-Landroid/os/ServiceManager;->addService(Ljava/lang/String;Landroid/os/IBinder;)V
-Landroid/os/ServiceManager;->addService(Ljava/lang/String;Landroid/os/IBinder;ZI)V
-Lcom/android/internal/os/PowerProfile;->readPowerValuesFromXml(Landroid/content/Context;Z)V
-Lcom/android/server/SystemConfig;->readPermission(Lorg/xmlpull/v1/XmlPullParser;Ljava/lang/String;)V
-Landroid/content/res/ResourcesImpl;-><init>(Landroid/content/res/AssetManager;Landroid/util/DisplayMetrics;Landroid/content/res/Configuration;Landroid/view/DisplayAdjustments;)V
-Landroid/os/ServiceManager;->getService(Ljava/lang/String;)Landroid/os/IBinder;
-Landroid/os/ServiceManager;->getServiceOrThrow(Ljava/lang/String;)Landroid/os/IBinder;
-Landroid/util/Base64$Decoder;->process([BIIZ)Z
-Lcom/android/internal/util/XmlUtils;->readLongAttribute(Lorg/xmlpull/v1/XmlPullParser;Ljava/lang/String;)J
-Lcom/android/internal/util/XmlUtils;->readLongAttribute(Lorg/xmlpull/v1/XmlPullParser;Ljava/lang/String;J)J
-Lcom/android/internal/os/BatteryStatsImpl$Uid;->getPackageStatsLocked(Ljava/lang/String;)Lcom/android/internal/os/BatteryStatsImpl$Uid$Pkg;
-Lcom/android/internal/app/procstats/ProcessStats;->resetCommon()V
-HPLcom/android/internal/app/procstats/ProcessStats;->resetSafely()V
-Landroid/content/res/ResourcesImpl;->updateConfiguration(Landroid/content/res/Configuration;Landroid/util/DisplayMetrics;Landroid/content/res/CompatibilityInfo;)V
-Landroid/content/res/Resources;-><init>()V
-Landroid/content/res/Resources;-><init>(Landroid/content/res/AssetManager;Landroid/util/DisplayMetrics;Landroid/content/res/Configuration;)V
-Landroid/content/res/Resources;-><init>(Ljava/lang/ClassLoader;)V
-Landroid/os/ServiceManager;->rawGetService(Ljava/lang/String;)Landroid/os/IBinder;
-Landroid/util/LongSparseArray;->put(JLjava/lang/Object;)V
-Landroid/util/ArrayMap;->freeArrays([I[Ljava/lang/Object;I)V
+Landroid/util/ArrayMap;->size()I
Landroid/util/ArrayMap;->keyAt(I)Ljava/lang/Object;
-Landroid/content/pm/PackageParser$Activity$1;->createFromParcel(Landroid/os/Parcel;)Landroid/content/pm/PackageParser$Activity;
-Landroid/content/pm/PackageParser$Activity$1;->createFromParcel(Landroid/os/Parcel;)Ljava/lang/Object;
-Landroid/content/pm/PackageParser$Activity;-><init>(Landroid/content/pm/PackageParser$ParseComponentArgs;Landroid/content/pm/ActivityInfo;)V
-Landroid/content/pm/PackageParser$Activity;-><init>(Landroid/os/Parcel;)V
-Landroid/content/res/AssetManager;->setConfiguration(IILjava/lang/String;IIIIIIIIIIIIIII)V
-Lcom/android/internal/os/BatteryStatsImpl$Counter;-><init>(Lcom/android/internal/os/BatteryStatsImpl$TimeBase;)V
-Lcom/android/internal/os/BatteryStatsImpl$Counter;-><init>(Lcom/android/internal/os/BatteryStatsImpl$TimeBase;Landroid/os/Parcel;)V
-Landroid/util/ArraySet;->allocArrays(I)V
-Landroid/os/storage/StorageManager;->isFileEncryptedNativeOnly()Z
-Lcom/android/internal/os/BatteryStatsImpl$Counter;->writeSummaryFromParcelLocked(Landroid/os/Parcel;)V
-Lcom/android/internal/os/BatteryStatsImpl;->updateRailStatsLocked()V
-Landroid/os/ServiceManagerProxy;->getService(Ljava/lang/String;)Landroid/os/IBinder;
-Landroid/util/SparseIntArray;-><init>()V
-Landroid/util/SparseIntArray;-><init>(I)V
-Lcom/android/internal/util/XmlUtils;->readIntAttribute(Lorg/xmlpull/v1/XmlPullParser;Ljava/lang/String;)I
-Lcom/android/internal/util/XmlUtils;->readIntAttribute(Lorg/xmlpull/v1/XmlPullParser;Ljava/lang/String;I)I
-Lcom/android/internal/os/BatteryStatsImpl$LongSamplingCounter;-><init>(Lcom/android/internal/os/BatteryStatsImpl$TimeBase;)V
-Lcom/android/internal/os/BatteryStatsImpl$LongSamplingCounter;-><init>(Lcom/android/internal/os/BatteryStatsImpl$TimeBase;Landroid/os/Parcel;)V
-Lcom/android/internal/os/BatteryStatsImpl;-><init>(Lcom/android/internal/os/BatteryStatsImpl$Clocks;Landroid/os/Parcel;)V
-Lcom/android/internal/os/BatteryStatsImpl;-><init>(Lcom/android/internal/os/BatteryStatsImpl$Clocks;Ljava/io/File;Landroid/os/Handler;Lcom/android/internal/os/BatteryStatsImpl$PlatformIdleStateCallback;Lcom/android/internal/os/BatteryStatsImpl$RailEnergyDataCallback;Lcom/android/internal/os/BatteryStatsImpl$UserInfoProvider;)V
-Lcom/android/internal/os/BatteryStatsImpl;-><init>(Ljava/io/File;Landroid/os/Handler;Lcom/android/internal/os/BatteryStatsImpl$PlatformIdleStateCallback;Lcom/android/internal/os/BatteryStatsImpl$RailEnergyDataCallback;Lcom/android/internal/os/BatteryStatsImpl$UserInfoProvider;)V
-Lcom/android/internal/os/BatteryStatsImpl$Uid;->readJobSummaryFromParcelLocked(Ljava/lang/String;Landroid/os/Parcel;)V
-Lcom/android/internal/app/procstats/ProcessStats;->updateFragmentation()V
-Landroid/os/Parcel;->readTypedObject(Landroid/os/Parcelable$Creator;)Ljava/lang/Object;
-Lcom/android/internal/os/BatteryStatsImpl$DurationTimer;->getTotalDurationMsLocked(J)J
-Landroid/os/Parcel;->createTypedArray(Landroid/os/Parcelable$Creator;)[Ljava/lang/Object;
-Landroid/os/Parcel;->createTypedArrayList(Landroid/os/Parcelable$Creator;)Ljava/util/ArrayList;
-Landroid/os/Parcel;->createTypedArrayMap(Landroid/os/Parcelable$Creator;)Landroid/util/ArrayMap;
-Landroid/content/pm/PackageParserCacheHelper$ReadHelper;->readString(Landroid/os/Parcel;)Ljava/lang/String;
-Lcom/android/server/LocalServices;->addService(Ljava/lang/Class;Ljava/lang/Object;)V
-Landroid/util/Slog;->d(Ljava/lang/String;Ljava/lang/String;)I
-Landroid/util/TimingsTraceLog;->traceBegin(Ljava/lang/String;)V
-Landroid/content/res/AssetManager;-><init>()V
-Landroid/content/res/AssetManager;->getResourceValue(IILandroid/util/TypedValue;Z)Z
-Landroid/util/LongSparseLongArray;->put(JJ)V
-Lcom/android/internal/os/BatteryStatsImpl$SystemClocks;->uptimeMillis()J
-Landroid/content/res/AssetManager;->setApkAssets([Landroid/content/res/ApkAssets;Z)V
-Lcom/android/internal/os/BatteryStatsImpl$LongSamplingCounterArray;->readSummaryFromParcelLocked(Landroid/os/Parcel;Lcom/android/internal/os/BatteryStatsImpl$TimeBase;)Lcom/android/internal/os/BatteryStatsImpl$LongSamplingCounterArray;
-Lcom/android/internal/util/XmlUtils;->readBooleanAttribute(Lorg/xmlpull/v1/XmlPullParser;Ljava/lang/String;)Z
-Lcom/android/internal/util/XmlUtils;->readBooleanAttribute(Lorg/xmlpull/v1/XmlPullParser;Ljava/lang/String;Z)Z
-Landroid/os/StrictMode$ThreadPolicy;-><init>(ILandroid/os/StrictMode$OnThreadViolationListener;Ljava/util/concurrent/Executor;)V
-Lcom/android/internal/os/KernelCpuSpeedReader;->readDelta()[J
-Lcom/android/internal/os/AtomicFile;->startWrite()Ljava/io/FileOutputStream;
-Landroid/app/ContextImpl;->createSystemUiContext(Landroid/app/ContextImpl;I)Landroid/app/ContextImpl;
-Landroid/app/ActivityThread;->getSystemUiContext()Landroid/app/ContextImpl;
-Landroid/os/Parcel;->recycle()V
-Landroid/util/Slog;->i(Ljava/lang/String;Ljava/lang/String;)I
-Landroid/os/Binder;-><init>()V
-Landroid/os/Binder;-><init>(Ljava/lang/String;)V
-Landroid/content/Context;->getSystemService(Ljava/lang/Class;)Ljava/lang/Object;
-Lcom/android/internal/util/ArrayUtils;->newUnpaddedLongArray(I)[J
-Landroid/content/res/ResourcesImpl;->getValue(ILandroid/util/TypedValue;Z)V
-Landroid/content/res/ResourcesImpl;->getValueForDensity(IILandroid/util/TypedValue;Z)V
-Landroid/util/LongSparseLongArray;-><init>()V
-Landroid/util/LongSparseLongArray;-><init>(I)V
-Landroid/os/BatteryStats$Timer;-><init>()V
-Lcom/android/internal/os/BatteryStatsImpl$Uid;->createAggregatedPartialWakelockTimerLocked()Lcom/android/internal/os/BatteryStatsImpl$DualTimer;
-Lcom/android/internal/os/BatteryStatsImpl$LongSamplingCounterArray;->access$2300(Lcom/android/internal/os/BatteryStatsImpl$LongSamplingCounterArray;Landroid/os/Parcel;)V
-Lcom/android/internal/os/BatteryStatsImpl$Uid;->readJobCompletionsFromParcelLocked(Landroid/os/Parcel;)V
-Landroid/util/MapCollections$KeySet;->iterator()Ljava/util/Iterator;
-Landroid/text/TextUtils;->isEmpty(Ljava/lang/CharSequence;)Z
-Lcom/android/internal/os/BatteryStatsImpl$TimeBase;->writeSummaryToParcel(Landroid/os/Parcel;JJ)V
-Lcom/android/internal/os/BatteryStatsImpl$StopwatchTimer;->computeRunTimeLocked(J)J
-Landroid/bluetooth/BluetoothAdapter;->getDefaultAdapter()Landroid/bluetooth/BluetoothAdapter;
-Landroid/content/pm/PackageParserCacheHelper$ReadHelper;->startAndInstall()V
-Landroid/content/pm/PackageItemInfo;-><init>(Landroid/content/pm/PackageItemInfo;)V
-Landroid/content/pm/PackageItemInfo;-><init>(Landroid/os/Parcel;)V
-Landroid/content/pm/ActivityInfo;-><init>()V
-Landroid/content/pm/ActivityInfo;-><init>(Landroid/content/pm/ActivityInfo;)V
-Landroid/content/pm/ActivityInfo;-><init>(Landroid/os/Parcel;)V
-Landroid/content/pm/ActivityInfo$1;->createFromParcel(Landroid/os/Parcel;)Landroid/content/pm/ActivityInfo;
-Landroid/content/pm/ActivityInfo$1;->createFromParcel(Landroid/os/Parcel;)Ljava/lang/Object;
-Landroid/os/BinderProxy;->transact(ILandroid/os/Parcel;Landroid/os/Parcel;I)Z
-Landroid/os/HandlerThread;->getLooper()Landroid/os/Looper;
-Landroid/os/FileUtils;->$closeResource(Ljava/lang/Throwable;Ljava/lang/AutoCloseable;)V
-Landroid/os/SystemProperties;->digestOf([Ljava/lang/String;)Ljava/lang/String;
-Lcom/android/internal/util/ArrayUtils;->isEmpty(Ljava/util/Collection;)Z
-Lcom/android/internal/util/ArrayUtils;->isEmpty([Ljava/lang/Object;)Z
-Landroid/util/AtomicFile;-><init>(Ljava/io/File;)V
-Landroid/util/AtomicFile;-><init>(Ljava/io/File;Ljava/lang/String;)V
-Landroid/util/LongSparseArray;-><init>()V
-Landroid/util/LongSparseArray;-><init>(I)V
-Landroid/content/res/Resources;->obtainTypedArray(I)Landroid/content/res/TypedArray;
-Landroid/util/AtomicFile;->openRead()Ljava/io/FileInputStream;
-Lcom/android/internal/os/BatteryStatsImpl$TimeBase;-><init>(Z)V
-Lcom/android/internal/os/BatteryStatsImpl$Counter;->readSummaryFromParcelLocked(Landroid/os/Parcel;)V
-Lcom/android/internal/os/BatteryStatsImpl$Uid;->makeProcessState(ILandroid/os/Parcel;)V
-Lcom/android/internal/os/BatteryStatsImpl$Uid$3;->instantiateObject()Lcom/android/internal/os/BatteryStatsImpl$DualTimer;
-Lcom/android/internal/os/BatteryStatsImpl$Uid$3;->instantiateObject()Ljava/lang/Object;
-Landroid/content/pm/PackageUserState;-><init>()V
-Landroid/app/ActivityManager;->isLowRamDeviceStatic()Z
-Lcom/android/internal/os/KernelCpuUidTimeReader$KernelCpuUidActiveTimeReader;->readDeltaImpl(Lcom/android/internal/os/KernelCpuUidTimeReader$Callback;)V
-Lcom/android/internal/os/BatteryStatsImpl;->updateRpmStatsLocked()V
-Lcom/android/internal/os/BatteryStatsImpl$LongSamplingCounter;->writeSummaryFromParcelLocked(Landroid/os/Parcel;)V
-Lcom/android/internal/os/KernelMemoryBandwidthStats;->updateStats()V
-Landroid/content/pm/PackageParser;->isCacheUpToDate(Ljava/io/File;Ljava/io/File;)Z
-Landroid/os/StrictMode;->initThreadDefaults(Landroid/content/pm/ApplicationInfo;)V
-Landroid/app/ResourcesManager;->getOrCreateResources(Landroid/os/IBinder;Landroid/content/res/ResourcesKey;Ljava/lang/ClassLoader;)Landroid/content/res/Resources;
-Landroid/app/ResourcesManager;->getOrCreateResourcesForActivityLocked(Landroid/os/IBinder;Ljava/lang/ClassLoader;Landroid/content/res/ResourcesImpl;Landroid/content/res/CompatibilityInfo;)Landroid/content/res/Resources;
-Landroid/app/ResourcesManager;->getOrCreateResourcesLocked(Ljava/lang/ClassLoader;Landroid/content/res/ResourcesImpl;Landroid/content/res/CompatibilityInfo;)Landroid/content/res/Resources;
-Landroid/app/ResourcesManager;->getResources(Landroid/os/IBinder;Ljava/lang/String;[Ljava/lang/String;[Ljava/lang/String;[Ljava/lang/String;ILandroid/content/res/Configuration;Landroid/content/res/CompatibilityInfo;Ljava/lang/ClassLoader;)Landroid/content/res/Resources;
-Landroid/app/ContextImpl;->createResources(Landroid/os/IBinder;Landroid/app/LoadedApk;Ljava/lang/String;ILandroid/content/res/Configuration;Landroid/content/res/CompatibilityInfo;[Ljava/lang/String;)Landroid/content/res/Resources;
-Landroid/app/ContextImpl;->createResources(Landroid/os/IBinder;Landroid/app/LoadedApk;Ljava/lang/String;ILandroid/content/res/Configuration;Landroid/content/res/CompatibilityInfo;)Landroid/content/res/Resources;
-Landroid/app/ContextImpl;->getSystemService(Ljava/lang/String;)Ljava/lang/Object;
-Landroid/app/ContextImpl;->getSystemServiceName(Ljava/lang/Class;)Ljava/lang/String;
-Landroid/app/SystemServiceRegistry$CachedServiceFetcher;->getService(Landroid/app/ContextImpl;)Ljava/lang/Object;
-Landroid/util/TimingsTraceLog;->assertSameThread()V
-Landroid/os/HandlerThread;-><init>(Ljava/lang/String;)V
-Landroid/os/HandlerThread;-><init>(Ljava/lang/String;I)V
-Lcom/android/internal/util/ArrayUtils;->newUnpaddedIntArray(I)[I
-Landroid/content/res/Configuration;-><init>()V
-Landroid/content/res/Configuration;-><init>(Landroid/content/res/Configuration;)V
-Landroid/view/SurfaceControl;->getInternalDisplayToken()Landroid/os/IBinder;
-Landroid/view/SurfaceControl;->getPhysicalDisplayToken(J)Landroid/os/IBinder;
-Landroid/content/res/Resources;->getInteger(I)I
-Landroid/os/Handler;->sendMessageAtTime(Landroid/os/Message;J)Z
-Lcom/android/internal/os/BatteryStatsImpl$TimeBase;->init(JJ)V
-Lcom/android/internal/os/BatteryStatsImpl$TimeBase;->readSummaryFromParcel(Landroid/os/Parcel;)V
-Lcom/android/internal/os/BatteryStatsImpl$Uid$Pkg;-><init>(Lcom/android/internal/os/BatteryStatsImpl;)V
-Landroid/util/ArraySet;->freeArrays([I[Ljava/lang/Object;I)V
-Landroid/util/ArrayMap;->entrySet()Ljava/util/Set;
-Lcom/android/internal/os/KernelCpuUidTimeReader$KernelCpuUidClusterTimeReader;->readDeltaImpl(Lcom/android/internal/os/KernelCpuUidTimeReader$Callback;)V
-Landroid/telephony/TelephonyManager;->getITelephony()Lcom/android/internal/telephony/ITelephony;
-Landroid/telephony/TelephonyManager;->requestModemActivityInfo(Landroid/os/ResultReceiver;)V
-Lcom/android/internal/os/BatteryStatsImpl$DurationTimer;->getMaxDurationMsLocked(J)J
-Lcom/android/internal/os/BatteryStatsImpl$SamplingTimer;->endSample()V
-Lcom/android/internal/os/BatteryStatsImpl;->updateKernelMemoryBandwidthLocked()V
-Landroid/content/pm/ComponentInfo;-><init>()V
-Landroid/content/pm/ComponentInfo;-><init>(Landroid/content/pm/ComponentInfo;)V
-Landroid/content/pm/ComponentInfo;-><init>(Landroid/os/Parcel;)V
-Landroid/view/SurfaceControl;->getDisplayConfigs(Landroid/os/IBinder;)[Landroid/view/SurfaceControl$PhysicalDisplayInfo;
-Lcom/android/internal/os/AtomicFile;->finishWrite(Ljava/io/FileOutputStream;)V
-Landroid/app/ResourcesManager;->createResourcesImpl(Landroid/content/res/ResourcesKey;)Landroid/content/res/ResourcesImpl;
-Landroid/app/ContextImpl;->updateDisplay(I)V
-Landroid/hardware/display/DisplayManagerGlobal;->getInstance()Landroid/hardware/display/DisplayManagerGlobal;
-Landroid/app/ResourcesManager;->getAdjustedDisplay(ILandroid/content/res/Resources;)Landroid/view/Display;
-Landroid/app/ResourcesManager;->getAdjustedDisplay(ILandroid/view/DisplayAdjustments;)Landroid/view/Display;
-Landroid/os/Parcel;->readStrongBinder()Landroid/os/IBinder;
-Landroid/app/ContextImpl;->setTheme(I)V
-Landroid/content/IntentFilter;->readFromXml(Lorg/xmlpull/v1/XmlPullParser;)V
-Landroid/text/TextUtils;->getLayoutDirectionFromLocale(Ljava/util/Locale;)I
-Landroid/os/Handler;-><init>()V
-Landroid/os/Handler;-><init>(Landroid/os/Handler$Callback;)V
-Landroid/os/Handler;-><init>(Landroid/os/Handler$Callback;Z)V
-Landroid/os/Handler;-><init>(Landroid/os/Looper;)V
-Landroid/os/Handler;-><init>(Landroid/os/Looper;Landroid/os/Handler$Callback;)V
-Landroid/os/Handler;-><init>(Landroid/os/Looper;Landroid/os/Handler$Callback;Z)V
-Landroid/os/Handler;-><init>(Z)V
-Landroid/os/Binder;->queryLocalInterface(Ljava/lang/String;)Landroid/os/IInterface;
-Landroid/content/pm/PackageParser;->isApkFile(Ljava/io/File;)Z
-Landroid/util/SparseIntArray;->put(II)V
-Landroid/content/pm/ApplicationInfo;->initForUser(I)V
-Landroid/os/BinderProxy;->getInstance(JJ)Landroid/os/BinderProxy;
-Landroid/content/pm/IntentFilterVerificationInfo;->getStringFromXml(Lorg/xmlpull/v1/XmlPullParser;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
-Landroid/app/SystemServiceRegistry$35;->createService(Landroid/app/ContextImpl;)Landroid/os/PowerManager;
-Landroid/app/SystemServiceRegistry$35;->createService(Landroid/app/ContextImpl;)Ljava/lang/Object;
-Landroid/util/ArrayMap;->containsKey(Ljava/lang/Object;)Z
-Landroid/app/WindowConfiguration;->setToDefaults()V
-Lcom/android/internal/util/MemInfoReader;->readMemInfo()V
-Landroid/util/LongSparseArray;->get(J)Ljava/lang/Object;
-Landroid/util/LongSparseArray;->get(JLjava/lang/Object;)Ljava/lang/Object;
-Landroid/util/Spline;->createSpline([F[F)Landroid/util/Spline;
-Landroid/os/PowerManager;->getDefaultScreenBrightnessSetting()I
-Landroid/view/Display;-><init>(Landroid/hardware/display/DisplayManagerGlobal;ILandroid/view/DisplayInfo;Landroid/content/res/Resources;)V
-Landroid/view/Display;-><init>(Landroid/hardware/display/DisplayManagerGlobal;ILandroid/view/DisplayInfo;Landroid/view/DisplayAdjustments;)V
-Landroid/view/Display;-><init>(Landroid/hardware/display/DisplayManagerGlobal;ILandroid/view/DisplayInfo;Landroid/view/DisplayAdjustments;Landroid/content/res/Resources;)V
-Landroid/net/Uri;->withAppendedPath(Landroid/net/Uri;Ljava/lang/String;)Landroid/net/Uri;
-Landroid/content/res/TypedArray;->obtain(Landroid/content/res/Resources;I)Landroid/content/res/TypedArray;
-Landroid/provider/Settings$System;->getUriFor(Ljava/lang/String;)Landroid/net/Uri;
-Landroid/util/MapCollections$ArrayIterator;->next()Ljava/lang/Object;
-Landroid/view/DisplayAdjustments;-><init>()V
-Landroid/view/DisplayAdjustments;-><init>(Landroid/content/res/Configuration;)V
-Landroid/view/DisplayAdjustments;-><init>(Landroid/view/DisplayAdjustments;)V
-Landroid/hardware/display/DisplayManager;->getOrCreateDisplayLocked(IZ)Landroid/view/Display;
-Landroid/content/res/Resources;->getIntArray(I)[I
-Landroid/content/res/StringBlock;->get(I)Ljava/lang/CharSequence;
-Landroid/content/res/XmlBlock$Parser;->getText()Ljava/lang/String;
-Lcom/android/internal/os/BatteryStatsImpl$LongSamplingCounter;->readSummaryFromParcelLocked(Landroid/os/Parcel;)V
-Lcom/android/internal/os/BatteryStatsImpl$Uid$Wakelock;-><init>(Lcom/android/internal/os/BatteryStatsImpl;Lcom/android/internal/os/BatteryStatsImpl$Uid;)V
-Lcom/android/internal/os/BatteryStatsImpl$Uid;->readSyncSummaryFromParcelLocked(Ljava/lang/String;Landroid/os/Parcel;)V
-Landroid/hardware/display/DisplayManagerGlobal;->getDisplayInfo(I)Landroid/view/DisplayInfo;
-Landroid/os/FileUtils;->readTextFile(Ljava/io/File;ILjava/lang/String;)Ljava/lang/String;
-Lcom/android/internal/app/procstats/ProcessStats;->buildTimePeriodStartClockStr()V
-Landroid/text/format/DateFormat;->format(Ljava/lang/CharSequence;J)Ljava/lang/CharSequence;
-Landroid/text/format/DateFormat;->format(Ljava/lang/CharSequence;Ljava/util/Calendar;)Ljava/lang/CharSequence;
-Landroid/text/format/DateFormat;->format(Ljava/lang/CharSequence;Ljava/util/Date;)Ljava/lang/CharSequence;
-Landroid/telephony/TelephonyManager;->from(Landroid/content/Context;)Landroid/telephony/TelephonyManager;
-Lcom/android/internal/os/BatteryStatsImpl$TimeBase;->getRealtime(J)J
-Lcom/android/internal/os/BatteryStatsImpl$LongSamplingCounterArray;->writeSummaryToParcelLocked(Landroid/os/Parcel;Lcom/android/internal/os/BatteryStatsImpl$LongSamplingCounterArray;)V
-Lcom/android/internal/os/BatteryStatsImpl$LongSamplingCounterArray;->access$2600(Lcom/android/internal/os/BatteryStatsImpl$LongSamplingCounterArray;Landroid/os/Parcel;)V
-Landroid/os/Parcel;->unmarshall([BII)V
-Landroid/content/pm/PackageParser$Package;->fixupOwner(Ljava/util/List;)V
-Landroid/content/res/Resources;->getBoolean(I)Z
-Landroid/content/res/AssetManager;->getResourceText(I)Ljava/lang/CharSequence;
-Landroid/content/res/AssetManager;->getResourceTextArray(I)[Ljava/lang/CharSequence;
-Landroid/content/res/Resources;->getText(I)Ljava/lang/CharSequence;
-HPLandroid/content/res/Resources;->getText(ILjava/lang/CharSequence;)Ljava/lang/CharSequence;
-Landroid/content/res/Resources;->getTextArray(I)[Ljava/lang/CharSequence;
-Landroid/os/MessageQueue;->next()Landroid/os/Message;
-Landroid/os/Parcel;->marshall()[B
-Lcom/android/internal/logging/EventLogTags;->writeCommitSysConfigFile(Ljava/lang/String;J)V
-Landroid/os/ThreadLocalWorkSource;->restore(J)V
-Landroid/os/Looper;->prepare()V
-Landroid/os/Looper;->prepareMainLooper()V
-Lcom/android/internal/app/procstats/ProcessStats;->splitAndParseNumbers(Ljava/lang/String;)[I
-Landroid/os/Trace;->traceEnd(J)V
-Landroid/os/Parcel;->readExceptionCode()I
-Landroid/os/Parcel;->readException()V
-Landroid/os/Parcel;->readException(ILjava/lang/String;)V
-Lcom/android/internal/util/StatLogger;->logDurationStat(IJ)J
-Landroid/content/res/ResourcesImpl$ThemeImpl;->applyStyle(IZ)V
-Landroid/content/res/Resources$Theme;->applyStyle(IZ)V
-Landroid/content/res/AssetManager;->applyStyleToTheme(JIZ)V
-Landroid/os/Trace;->isTagEnabled(J)Z
-Lcom/android/internal/util/ArrayUtils;->containsAll([Ljava/lang/Object;[Ljava/lang/Object;)Z
-Landroid/os/Trace;->traceBegin(JLjava/lang/String;)V
-Landroid/hardware/display/DisplayManager;-><init>(Landroid/content/Context;)V
-Landroid/os/Bundle;-><init>()V
-Landroid/os/Bundle;-><init>(I)V
-Landroid/os/Bundle;-><init>(Landroid/os/Bundle;)V
-Landroid/os/Bundle;-><init>(Landroid/os/PersistableBundle;)V
-Landroid/content/pm/PackageBackwardCompatibility;->updatePackage(Landroid/content/pm/PackageParser$Package;)V
-Landroid/content/pm/PackageBackwardCompatibility;->modifySharedLibraries(Landroid/content/pm/PackageParser$Package;)V
-Landroid/content/pm/Signature;->areExactMatch([Landroid/content/pm/Signature;[Landroid/content/pm/Signature;)Z
-Lcom/android/internal/util/ArrayUtils;->contains(Ljava/util/Collection;Ljava/lang/Object;)Z
-Lcom/android/internal/util/ArrayUtils;->contains([II)Z
-Lcom/android/internal/util/ArrayUtils;->contains([Ljava/lang/Object;Ljava/lang/Object;)Z
-Lcom/android/internal/util/ConcurrentUtils$1;->newThread(Ljava/lang/Runnable;)Ljava/lang/Thread;
-Landroid/os/PowerManager;-><init>(Landroid/content/Context;Landroid/os/IPowerManager;Landroid/os/Handler;)V
-Landroid/content/res/AssetManager;->getResourceArray(I[I)I
-Landroid/content/res/AssetManager;->getResourceArraySize(I)I
-Landroid/app/WindowConfiguration;-><init>()V
-Landroid/view/SurfaceControl;->getPhysicalDisplayIds()[J
-Lcom/android/internal/os/BackgroundThread;->getHandler()Landroid/os/Handler;
-Landroid/net/Uri$StringUri;->buildUpon()Landroid/net/Uri$Builder;
-Lcom/android/internal/os/AtomicFile;->readFully()[B
-Lcom/android/internal/util/ArrayUtils;->indexOf([Ljava/lang/Object;Ljava/lang/Object;)I
-Landroid/content/res/ResourcesImpl;->loadXmlResourceParser(Ljava/lang/String;IILjava/lang/String;)Landroid/content/res/XmlResourceParser;
-Landroid/content/res/Resources;->loadXmlResourceParser(ILjava/lang/String;)Landroid/content/res/XmlResourceParser;
-Landroid/content/res/Resources;->getXml(I)Landroid/content/res/XmlResourceParser;
+Landroid/util/ArrayMap;->valueAt(I)Ljava/lang/Object;
+Landroid/util/ArrayMap;->binarySearchHashes([III)I
+Landroid/text/FontConfig$Family;->getName()Ljava/lang/String;
+Landroid/graphics/fonts/SystemFonts;->createFontFamily(Ljava/lang/String;Ljava/util/List;Ljava/lang/String;ILjava/util/Map;Ljava/util/ArrayList;)Landroid/graphics/fonts/FontFamily;
+Landroid/graphics/fonts/FontFamily$Builder;->build(Ljava/lang/String;IZ)Landroid/graphics/fonts/FontFamily;
+Landroid/graphics/fonts/Font$Builder;->build()Landroid/graphics/fonts/Font;
+Landroid/text/FontConfig$Font;->getFontName()Ljava/lang/String;
+Landroid/graphics/fonts/Font$Builder;-><init>(Ljava/nio/ByteBuffer;Ljava/io/File;Ljava/lang/String;)V
+Landroid/graphics/fonts/Font$Builder;-><init>(Ljava/nio/ByteBuffer;)V
+Landroid/text/FontConfig$Font;->getWeight()I
+Landroid/graphics/fonts/Font$Builder;->setWeight(I)Landroid/graphics/fonts/Font$Builder;
+Lcom/android/internal/util/Preconditions;->checkArgument(Z)V
+Landroid/text/FontConfig$Font;->isItalic()Z
+Landroid/graphics/fonts/Font$Builder;->setSlant(I)Landroid/graphics/fonts/Font$Builder;
+Landroid/text/FontConfig$Font;->getTtcIndex()I
+Landroid/graphics/fonts/Font$Builder;->setTtcIndex(I)Landroid/graphics/fonts/Font$Builder;
+Landroid/text/FontConfig$Font;->getAxes()[Landroid/graphics/fonts/FontVariationAxis;
+Landroid/graphics/fonts/Font$Builder;->setFontVariationSettings([Landroid/graphics/fonts/FontVariationAxis;)Landroid/graphics/fonts/Font$Builder;
+Landroid/graphics/fonts/FontStyle;-><init>(II)V
+Landroid/graphics/fonts/Font;-><init>(JLjava/nio/ByteBuffer;Ljava/io/File;Landroid/graphics/fonts/FontStyle;I[Landroid/graphics/fonts/FontVariationAxis;Ljava/lang/String;Landroid/graphics/fonts/Font$1;)V
+Landroid/graphics/fonts/Font;-><init>(JLjava/nio/ByteBuffer;Ljava/io/File;Landroid/graphics/fonts/FontStyle;I[Landroid/graphics/fonts/FontVariationAxis;Ljava/lang/String;)V
+Landroid/graphics/fonts/FontFamily$Builder;->makeStyleIdentifier(Landroid/graphics/fonts/Font;)I
+Landroid/graphics/fonts/FontStyle;->getWeight()I
+Landroid/graphics/fonts/FontStyle;->getSlant()I
+Landroid/graphics/fonts/Font;->getNativePtr()J
+Landroid/graphics/fonts/SystemFonts;->buildSystemFallback(Ljava/lang/String;Ljava/lang/String;Landroid/graphics/fonts/FontCustomizationParser$Result;Landroid/util/ArrayMap;Ljava/util/ArrayList;)[Landroid/text/FontConfig$Alias;
+Landroid/graphics/fonts/SystemFonts;->$closeResource(Ljava/lang/Throwable;Ljava/lang/AutoCloseable;)V
+Landroid/graphics/fonts/SystemFonts;->mmap(Ljava/lang/String;)Ljava/nio/ByteBuffer;
+Landroid/graphics/Typeface;->createFromFamilies([Landroid/graphics/fonts/FontFamily;)Landroid/graphics/Typeface;
+Landroid/graphics/fonts/FontFamily;->getNativePtr()J
+Landroid/content/pm/ActivityInfo;->activityInfoConfigNativeToJava(I)I
+Landroid/content/res/TypedArray;->getChangingConfigurations()I
+Landroid/content/res/TypedArray;->extractThemeAttrs([I)[I
+Landroid/util/ContainerHelpers;->binarySearch([JIJ)I
+Landroid/util/Pools$SimplePool;->isInPool(Ljava/lang/Object;)Z
+Landroid/content/res/ResourcesImpl;->getAssets()Landroid/content/res/AssetManager;
Landroid/content/res/XmlBlock$Parser;->next()I
-Landroid/content/res/XmlBlock$Parser;->nextTag()I
-Landroid/content/res/XmlBlock$Parser;->nextText()Ljava/lang/String;
-Lcom/google/android/collect/Sets;->newArraySet()Landroid/util/ArraySet;
-Lcom/google/android/collect/Sets;->newArraySet([Ljava/lang/Object;)Landroid/util/ArraySet;
-Landroid/util/ArraySet;->contains(Ljava/lang/Object;)Z
-Lcom/android/internal/os/BatteryStatsImpl$Uid;->getSensorTimerLocked(IZ)Lcom/android/internal/os/BatteryStatsImpl$DualTimer;
-Landroid/content/pm/PackageParser$SigningDetails;->hasCertificate(Landroid/content/pm/Signature;)Z
-Landroid/content/pm/PackageParser$SigningDetails;->hasCertificateInternal(Landroid/content/pm/Signature;I)Z
-Landroid/content/res/XmlBlock$Parser;->getAttributeValue(I)Ljava/lang/String;
-Landroid/content/res/XmlBlock$Parser;->getAttributeValue(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
+Landroid/content/res/XmlBlock$Parser;->getDepth()I
+Landroid/content/res/StringBlock;->get(I)Ljava/lang/CharSequence;
+Landroid/content/res/Resources;->getDisplayMetrics()Landroid/util/DisplayMetrics;
+Landroid/content/res/ResourcesImpl;->getDisplayMetrics()Landroid/util/DisplayMetrics;
+Landroid/content/res/TypedArray;->length()I
+Landroid/content/res/AssetManager;->ensureValidLocked()V
+Landroid/content/res/TypedArray;->getFloat(IF)F
+Landroid/content/res/ResourcesImpl;->loadXmlResourceParser(Ljava/lang/String;IILjava/lang/String;)Landroid/content/res/XmlResourceParser;
+Landroid/content/res/XmlBlock$Parser;->getName()Ljava/lang/String;
+Landroid/content/res/Resources;->getAssets()Landroid/content/res/AssetManager;
+Landroid/content/res/TypedArray;->obtain(Landroid/content/res/Resources;I)Landroid/content/res/TypedArray;
+Landroid/util/Pools$SynchronizedPool;->acquire()Ljava/lang/Object;
+Landroid/util/Pools$SimplePool;->acquire()Ljava/lang/Object;
+Landroid/content/res/TypedArray;->resize(I)V
+Landroid/content/res/Resources;->obtainAttributes(Landroid/util/AttributeSet;[I)Landroid/content/res/TypedArray;
+Landroid/content/res/AssetManager;->retrieveAttributes(Landroid/content/res/XmlBlock$Parser;[I[I[I)Z
+Landroid/content/res/TypedArray;->recycle()V
+Landroid/util/Pools$SynchronizedPool;->release(Ljava/lang/Object;)Z
+Landroid/util/Pools$SimplePool;->release(Ljava/lang/Object;)Z
+Landroid/graphics/drawable/Drawable;->obtainAttributes(Landroid/content/res/Resources;Landroid/content/res/Resources$Theme;Landroid/util/AttributeSet;[I)Landroid/content/res/TypedArray;
+Landroid/graphics/drawable/VectorDrawable$VGroup;->setTree(Lcom/android/internal/util/VirtualRefBasePtr;)V
+Landroid/graphics/drawable/VectorDrawable$VGroup;->getNativeSize()I
+Landroid/graphics/Rect;-><init>()V
+Landroid/graphics/drawable/VectorDrawable$VObject;->setTree(Lcom/android/internal/util/VirtualRefBasePtr;)V
+Lcom/android/internal/util/GrowingArrayUtils;->insert([IIII)[I
+Lcom/android/internal/util/GrowingArrayUtils;->insert([Ljava/lang/Object;IILjava/lang/Object;)[Ljava/lang/Object;
+Landroid/graphics/drawable/Drawable;->resolveDensity(Landroid/content/res/Resources;I)I
+Landroid/graphics/drawable/VectorDrawable$VObject;-><init>()V
+Landroid/util/ArrayMap;->freeArrays([I[Ljava/lang/Object;I)V
+Landroid/content/res/TypedArray;->extractThemeAttrs()[I
+Landroid/content/res/TypedArray;->getDimensionPixelSize(II)I
+Landroid/graphics/drawable/Drawable$ConstantState;-><init>()V
+Landroid/content/res/TypedArray;->getValueAt(ILandroid/util/TypedValue;)Z
+Landroid/content/res/ColorStateList;->inflate(Landroid/content/res/Resources;Lorg/xmlpull/v1/XmlPullParser;Landroid/util/AttributeSet;Landroid/content/res/Resources$Theme;)V
+Landroid/content/res/XmlBlock$Parser;->getAttributeNameResource(I)I
+Landroid/content/res/XmlBlock;->access$1200(JI)I
+Landroid/util/LongSparseArray;->put(JLjava/lang/Object;)V
+Lcom/android/internal/util/GrowingArrayUtils;->append([Ljava/lang/Object;ILjava/lang/Object;)[Ljava/lang/Object;
+Landroid/content/res/XmlBlock;->decOpenCountLocked()V
+Landroid/content/res/XmlBlock$Parser;->close()V
+Landroid/content/res/XmlBlock;->close()V
+Landroid/util/ArrayMap;-><init>()V
+Landroid/util/ArrayMap;-><init>(IZ)V
+Landroid/util/ArrayMap;->put(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
+Lcom/android/internal/util/XmlUtils;->nextElementWithin(Lorg/xmlpull/v1/XmlPullParser;I)Z
+Landroid/util/ArraySet;->indexOf(Ljava/lang/Object;I)I
+Landroid/util/ArraySet;->add(Ljava/lang/Object;)Z
+Landroid/text/TextUtils;->isEmpty(Ljava/lang/CharSequence;)Z
+Lcom/android/server/SystemConfig;->readPrivAppPermissions(Lorg/xmlpull/v1/XmlPullParser;Landroid/util/ArrayMap;Landroid/util/ArrayMap;)V
+Lcom/android/internal/util/XmlUtils;->nextElement(Lorg/xmlpull/v1/XmlPullParser;)V
+Lcom/android/server/SystemConfig;->readPermissionsFromXml(Ljava/io/File;I)V
+Lcom/android/server/SystemConfig;->addFeature(Ljava/lang/String;I)V
+Lcom/android/internal/util/XmlUtils;->skipCurrentTag(Lorg/xmlpull/v1/XmlPullParser;)V
+Landroid/os/Parcel;->readInt()I
+Landroid/os/Parcel;->readLong()J
+Lcom/android/internal/os/BatteryStatsImpl$TimeBase;->add(Lcom/android/internal/os/BatteryStatsImpl$TimeBaseObs;)V
+Lcom/android/internal/os/BatteryStatsImpl$Timer;-><init>(Lcom/android/internal/os/BatteryStatsImpl$Clocks;ILcom/android/internal/os/BatteryStatsImpl$TimeBase;)V
+Landroid/os/BatteryStats$Timer;-><init>()V
+Lcom/android/internal/os/BatteryStatsImpl$Timer;->readSummaryFromParcelLocked(Landroid/os/Parcel;)V
+Lcom/android/internal/os/BatteryStatsImpl;->readSummaryFromParcel(Landroid/os/Parcel;)V
+Landroid/os/Parcel;->access$000(Landroid/os/Parcel;)J
+Landroid/os/Parcel;->readString()Ljava/lang/String;
+Landroid/os/Parcel$ReadWriteHelper;->readString(Landroid/os/Parcel;)Ljava/lang/String;
+Lcom/android/internal/os/BatteryStatsImpl$SamplingTimer;-><init>(Lcom/android/internal/os/BatteryStatsImpl$Clocks;Lcom/android/internal/os/BatteryStatsImpl$TimeBase;)V
+Lcom/android/internal/os/BatteryStatsImpl$TimeBase;->isRunning()Z
+Lcom/android/internal/os/BatteryStatsImpl;->getKernelWakelockTimerLocked(Ljava/lang/String;)Lcom/android/internal/os/BatteryStatsImpl$SamplingTimer;
+Landroid/util/ArraySet;->freeArrays([I[Ljava/lang/Object;I)V
+Landroid/util/ArraySet;->allocArrays(I)V
+Lcom/android/internal/os/BatteryStatsImpl$StopwatchTimer;-><init>(Lcom/android/internal/os/BatteryStatsImpl$Clocks;Lcom/android/internal/os/BatteryStatsImpl$Uid;ILjava/util/ArrayList;Lcom/android/internal/os/BatteryStatsImpl$TimeBase;)V
+Lcom/android/internal/os/BatteryStatsImpl$StopwatchTimer;->readSummaryFromParcelLocked(Landroid/os/Parcel;)V
Lcom/android/internal/os/BatteryStatsImpl;->detachIfNotNull(Lcom/android/internal/os/BatteryStatsImpl$TimeBaseObs;)V
Lcom/android/internal/os/BatteryStatsImpl;->detachIfNotNull([Lcom/android/internal/os/BatteryStatsImpl$TimeBaseObs;)V
-Lcom/android/internal/os/BatteryStatsImpl;->detachIfNotNull([[Lcom/android/internal/os/BatteryStatsImpl$TimeBaseObs;)V
-Landroid/util/Spline$MonotoneCubicSpline;-><init>([F[F)V
-Landroid/content/res/Configuration;->setTo(Landroid/content/res/Configuration;)V
-Landroid/content/res/Configuration;->setToDefaults()V
-Lcom/android/server/SystemConfig;->readSplitPermission(Lorg/xmlpull/v1/XmlPullParser;Ljava/io/File;)V
-Lcom/android/internal/os/RpmStats;->getSubsystem(Ljava/lang/String;)Lcom/android/internal/os/RpmStats$PowerStateSubsystem;
-Lcom/android/internal/os/BatteryStatsImpl$TimeBase;->computeRealtime(JI)J
+Lcom/android/internal/os/BatteryStatsImpl$DurationTimer;-><init>(Lcom/android/internal/os/BatteryStatsImpl$Clocks;Lcom/android/internal/os/BatteryStatsImpl$Uid;ILjava/util/ArrayList;Lcom/android/internal/os/BatteryStatsImpl$TimeBase;)V
+Lcom/android/internal/os/BatteryStatsImpl$DurationTimer;->readSummaryFromParcelLocked(Landroid/os/Parcel;)V
+Lcom/android/internal/os/BatteryStatsImpl$LongSamplingCounter;-><init>(Lcom/android/internal/os/BatteryStatsImpl$TimeBase;)V
+Landroid/os/BatteryStats$LongCounter;-><init>()V
+Lcom/android/internal/os/BatteryStatsImpl$LongSamplingCounter;->readSummaryFromParcelLocked(Landroid/os/Parcel;)V
+Landroid/util/ArrayMap;->allocArrays(I)V
+Lcom/android/internal/os/BatteryStatsImpl$DualTimer;-><init>(Lcom/android/internal/os/BatteryStatsImpl$Clocks;Lcom/android/internal/os/BatteryStatsImpl$Uid;ILjava/util/ArrayList;Lcom/android/internal/os/BatteryStatsImpl$TimeBase;Lcom/android/internal/os/BatteryStatsImpl$TimeBase;)V
+Lcom/android/internal/os/BatteryStatsImpl$DualTimer;->readSummaryFromParcelLocked(Landroid/os/Parcel;)V
+Landroid/util/SparseArray;->put(ILjava/lang/Object;)V
+Lcom/android/internal/os/BatteryStatsImpl$OverflowArrayMap;-><init>(Lcom/android/internal/os/BatteryStatsImpl;I)V
+Lcom/android/internal/os/BatteryStatsImpl$OverflowArrayMap;->add(Ljava/lang/String;Ljava/lang/Object;)V
+Lcom/android/internal/os/BatteryStatsImpl$Uid;->getPackageStatsLocked(Ljava/lang/String;)Lcom/android/internal/os/BatteryStatsImpl$Uid$Pkg;
+Lcom/android/internal/util/ArrayUtils;->newUnpaddedObjectArray(I)[Ljava/lang/Object;
+Landroid/util/SparseArray;-><init>(I)V
+Landroid/util/SparseArray;-><init>()V
+Lcom/android/internal/os/BatteryStatsImpl$Uid;->readWakeSummaryFromParcelLocked(Ljava/lang/String;Landroid/os/Parcel;)V
+Lcom/android/internal/os/BatteryStatsImpl$Uid$Wakelock;-><init>(Lcom/android/internal/os/BatteryStatsImpl;Lcom/android/internal/os/BatteryStatsImpl$Uid;)V
+Landroid/os/BatteryStats$Uid$Wakelock;-><init>()V
+Lcom/android/internal/os/BatteryStatsImpl$Uid;->getWakelockTimerLocked(Lcom/android/internal/os/BatteryStatsImpl$Uid$Wakelock;I)Lcom/android/internal/os/BatteryStatsImpl$StopwatchTimer;
+Lcom/android/internal/os/BatteryStatsImpl$Counter;-><init>(Lcom/android/internal/os/BatteryStatsImpl$TimeBase;)V
+Landroid/os/BatteryStats$Counter;-><init>()V
+Lcom/android/internal/os/BatteryStatsImpl$Counter;->readSummaryFromParcelLocked(Landroid/os/Parcel;)V
+Lcom/android/internal/os/BatteryStatsImpl$TimeBase;-><init>(Z)V
+Lcom/android/internal/os/BatteryStatsImpl$TimeBase;->init(JJ)V
+Lcom/android/internal/os/BatteryStatsImpl$TimeBase;->getUptime(J)J
+Lcom/android/internal/os/BatteryStatsImpl$TimeBase;->getRealtime(J)J
+Lcom/android/internal/os/BatteryStatsImpl$TimeBase;->readSummaryFromParcel(Landroid/os/Parcel;)V
+Lcom/android/internal/os/BatteryStatsImpl$SystemClocks;->uptimeMillis()J
+Lcom/android/internal/os/BatteryStatsImpl$SystemClocks;->elapsedRealtime()J
+Lcom/android/internal/os/BatteryStatsImpl$LongSamplingCounterArray;->readSummaryFromParcelLocked(Landroid/os/Parcel;Lcom/android/internal/os/BatteryStatsImpl$TimeBase;)Lcom/android/internal/os/BatteryStatsImpl$LongSamplingCounterArray;
+Lcom/android/internal/os/BatteryStatsImpl$Uid;->getServiceStatsLocked(Ljava/lang/String;Ljava/lang/String;)Lcom/android/internal/os/BatteryStatsImpl$Uid$Pkg$Serv;
+Lcom/android/internal/os/BatteryStatsImpl$Uid$Pkg;->newServiceStatsLocked()Lcom/android/internal/os/BatteryStatsImpl$Uid$Pkg$Serv;
+Lcom/android/internal/os/BatteryStatsImpl$Uid$Pkg$Serv;-><init>(Lcom/android/internal/os/BatteryStatsImpl;)V
+Landroid/os/BatteryStats$Uid$Pkg$Serv;-><init>()V
+Lcom/android/internal/app/procstats/ProcessStats;->splitAndParseNumbers(Ljava/lang/String;)[I
+Lcom/android/internal/os/KernelCpuProcStringReader;->isNumber(C)Z
+Lcom/android/internal/os/KernelCpuProcStringReader;->access$000(Lcom/android/internal/os/KernelCpuProcStringReader;)[C
+Lcom/android/internal/os/KernelCpuProcStringReader$ProcFileIterator;->nextLine()Ljava/nio/CharBuffer;
+Lcom/android/internal/os/KernelCpuProcStringReader;->asLongs(Ljava/nio/CharBuffer;[J)I
+Landroid/util/SparseArray;->get(I)Ljava/lang/Object;
+Landroid/util/SparseArray;->get(ILjava/lang/Object;)Ljava/lang/Object;
+Lcom/android/internal/os/KernelCpuUidTimeReader$KernelCpuUidFreqTimeReader;->copyToCurTimes()V
+Lcom/android/internal/os/KernelCpuUidTimeReader$KernelCpuUidFreqTimeReader;->readDeltaImpl(Lcom/android/internal/os/KernelCpuUidTimeReader$Callback;)V
+Lcom/android/internal/os/KernelWakelockReader;->readKernelWakelockStats(Lcom/android/internal/os/KernelWakelockStats;)Lcom/android/internal/os/KernelWakelockStats;
+Lcom/android/internal/util/GrowingArrayUtils;->insert([JIIJ)[J
+Lcom/android/internal/util/XmlUtils;->readIntAttribute(Lorg/xmlpull/v1/XmlPullParser;Ljava/lang/String;I)I
+Lcom/android/internal/util/XmlUtils;->readLongAttribute(Lorg/xmlpull/v1/XmlPullParser;Ljava/lang/String;J)J
Landroid/os/Parcel;->dataPosition()I
-Lcom/android/internal/os/BatteryStatsImpl$DurationTimer;->getCurrentDurationMsLocked(J)J
-Lcom/android/internal/os/KernelCpuUidTimeReader$KernelCpuUidFreqTimeReader;->checkPrecondition(Lcom/android/internal/os/KernelCpuProcStringReader$ProcFileIterator;)Z
+Landroid/util/LongSparseLongArray;->put(JJ)V
+Lcom/android/internal/util/ArrayUtils;->newUnpaddedLongArray(I)[J
+Lcom/android/internal/os/KernelWakelockReader;->parseProcWakelocks([BIZLcom/android/internal/os/KernelWakelockStats;)Lcom/android/internal/os/KernelWakelockStats;
+Landroid/util/SparseArray;->valueAt(I)Ljava/lang/Object;
+Landroid/util/LongSparseLongArray;-><init>()V
+Landroid/util/LongSparseLongArray;-><init>(I)V
+Landroid/app/AppOpsManager;->makeKey(II)J
+Landroid/app/AppOpsManager;->opToDefaultMode(I)I
+Lcom/android/internal/util/XmlUtils;->readLongAttribute(Lorg/xmlpull/v1/XmlPullParser;Ljava/lang/String;)J
+Landroid/app/AppOpsManager;->extractFlagsFromKey(J)I
+Landroid/app/AppOpsManager;->extractUidStateFromKey(J)I
+Lcom/android/internal/util/XmlUtils;->readStringAttribute(Lorg/xmlpull/v1/XmlPullParser;Ljava/lang/String;)Ljava/lang/String;
+Lcom/android/internal/os/KernelWakelockStats$Entry;-><init>(IJI)V
+Lcom/android/internal/os/KernelWakelockReader;->removeOldStats(Lcom/android/internal/os/KernelWakelockStats;)Lcom/android/internal/os/KernelWakelockStats;
+Lcom/android/internal/os/BatteryStatsImpl;->updateKernelWakelocksLocked()V
+Lcom/android/internal/os/BatteryStatsImpl$SamplingTimer;->update(JI)V
+Lcom/android/internal/os/BatteryStatsImpl$SamplingTimer;->setUpdateVersion(I)V
+Lcom/android/internal/os/BatteryStatsImpl$SamplingTimer;->getUpdateVersion()I
+Lcom/android/internal/os/BatteryStatsImpl$SamplingTimer;->endSample()V
Lcom/android/internal/os/BatteryStatsImpl$SamplingTimer;->computeRunTimeLocked(J)J
Lcom/android/internal/os/BatteryStatsImpl$SamplingTimer;->computeCurrentCountLocked()I
-Lcom/android/internal/os/KernelMemoryBandwidthStats;->parseStats(Ljava/io/BufferedReader;)V
-Landroid/util/MapCollections;->getEntrySet()Ljava/util/Set;
-Landroid/util/MapCollections$EntrySet;->iterator()Ljava/util/Iterator;
-Lcom/android/internal/os/BatteryStatsImpl$Uid;->writeJobCompletionsToParcelLocked(Landroid/os/Parcel;)V
+Landroid/os/Parcel;->writeInt(I)V
+Landroid/os/Parcel;->writeLong(J)V
+Lcom/android/internal/os/BatteryStatsImpl$Timer;->writeSummaryFromParcelLocked(Landroid/os/Parcel;J)V
+Lcom/android/internal/os/BatteryStatsImpl;->writeSummaryToParcel(Landroid/os/Parcel;Z)V
+Landroid/os/Parcel;->writeString(Ljava/lang/String;)V
+Landroid/os/Parcel$ReadWriteHelper;->writeString(Landroid/os/Parcel;Ljava/lang/String;)V
+Landroid/os/StrictMode;->setThreadPolicyMask(I)V
+Landroid/os/StrictMode;->setBlockGuardPolicy(I)V
+Lcom/android/internal/os/ProcStatsUtil;->readTerminatedProcFile(Ljava/lang/String;B)Ljava/lang/String;
+Landroid/os/StrictMode$ThreadPolicy;-><init>(ILandroid/os/StrictMode$OnThreadViolationListener;Ljava/util/concurrent/Executor;Landroid/os/StrictMode$1;)V
+Landroid/os/StrictMode$ThreadPolicy;-><init>(ILandroid/os/StrictMode$OnThreadViolationListener;Ljava/util/concurrent/Executor;)V
+Landroid/os/StrictMode;->setThreadPolicy(Landroid/os/StrictMode$ThreadPolicy;)V
+Landroid/os/StrictMode;->allowThreadDiskReadsMask()I
+Landroid/os/StrictMode;->getThreadPolicyMask()I
+Landroid/os/StrictMode;->allowThreadDiskReads()Landroid/os/StrictMode$ThreadPolicy;
+Lcom/android/internal/os/ProcessCpuTracker;->collectStats(Ljava/lang/String;IZ[ILjava/util/ArrayList;)[I
+Lcom/android/internal/os/ProcessCpuTracker$Stats;-><init>(IIZ)V
+Lcom/android/internal/os/ProcessCpuTracker$Stats;->getUid(Ljava/lang/String;)I
+Lcom/android/internal/os/ProcessCpuTracker;->getName(Lcom/android/internal/os/ProcessCpuTracker$Stats;Ljava/lang/String;)V
+Lcom/android/internal/os/ProcessCpuTracker;->onMeasureProcessName(Ljava/lang/String;)I
+Lcom/android/internal/os/BatteryStatsImpl$StopwatchTimer;->computeRunTimeLocked(J)J
+Lcom/android/internal/os/BatteryStatsImpl$StopwatchTimer;->computeCurrentCountLocked()I
+Lcom/android/internal/os/BatteryStatsImpl$DurationTimer;->writeSummaryFromParcelLocked(Landroid/os/Parcel;J)V
+Lcom/android/internal/os/BatteryStatsImpl$DurationTimer;->getMaxDurationMsLocked(J)J
+Lcom/android/internal/os/BatteryStatsImpl$DurationTimer;->getTotalDurationMsLocked(J)J
+Lcom/android/internal/os/BatteryStatsImpl$DurationTimer;->getCurrentDurationMsLocked(J)J
+Lcom/android/internal/os/BatteryStatsImpl$LongSamplingCounter;->writeSummaryFromParcelLocked(Landroid/os/Parcel;)V
+Lcom/android/internal/os/BatteryStatsImpl$DualTimer;->writeSummaryFromParcelLocked(Landroid/os/Parcel;J)V
+Lcom/android/internal/os/BatteryStatsImpl$OverflowArrayMap;->getMap()Landroid/util/ArrayMap;
+Lcom/android/internal/os/BatteryStatsImpl$Uid;->access$2400(Lcom/android/internal/os/BatteryStatsImpl$Uid;)Lcom/android/internal/os/BatteryStatsImpl$LongSamplingCounter;
+Lcom/android/internal/os/BatteryStatsImpl$Uid;->access$2500(Lcom/android/internal/os/BatteryStatsImpl$Uid;)Lcom/android/internal/os/BatteryStatsImpl$LongSamplingCounter;
+Lcom/android/internal/os/BatteryStatsImpl$Counter;->writeSummaryFromParcelLocked(Landroid/os/Parcel;)V
+Lcom/android/internal/os/BatteryStatsImpl$TimeBase;->writeSummaryToParcel(Landroid/os/Parcel;JJ)V
+Lcom/android/internal/os/BatteryStatsImpl$TimeBase;->computeUptime(JI)J
+Lcom/android/internal/os/BatteryStatsImpl$TimeBase;->computeRealtime(JI)J
+Lcom/android/internal/os/BatteryStatsImpl$LongSamplingCounterArray;->writeSummaryToParcelLocked(Landroid/os/Parcel;Lcom/android/internal/os/BatteryStatsImpl$LongSamplingCounterArray;)V
+Lcom/android/internal/os/BatteryStatsImpl$Uid$Pkg$Serv;->getStartTimeToNowLocked(J)J
+Landroid/util/MapCollections$ArrayIterator;->hasNext()Z
+Landroid/util/SparseArray;->size()I
+Landroid/content/pm/Signature;->parseHexDigit(I)I
+Landroid/content/pm/Signature;-><init>(Ljava/lang/String;)V
+Landroid/content/pm/FallbackCategoryProvider;->loadFallbacks()V
+Landroid/content/pm/PermissionInfo;->fixProtectionLevel(I)I
+Lcom/android/internal/util/ArrayUtils;->isEmpty([I)Z
+Lcom/android/internal/util/ArrayUtils;->appendInt([IIZ)[I
+Landroid/util/ArraySet;-><init>(IZ)V
+Landroid/content/pm/IntentFilterVerificationInfo;->readFromXml(Lorg/xmlpull/v1/XmlPullParser;)V
+Landroid/content/pm/IntentFilterVerificationInfo;->getStringFromXml(Lorg/xmlpull/v1/XmlPullParser;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
+Landroid/content/pm/PackageParser;->toSigningKeys([Landroid/content/pm/Signature;)Landroid/util/ArraySet;
+Landroid/util/ArraySet;-><init>(I)V
+Landroid/util/Base64$Decoder;->process([BIIZ)Z
+Landroid/util/LongSparseArray;->get(J)Ljava/lang/Object;
+Landroid/util/LongSparseArray;->get(JLjava/lang/Object;)Ljava/lang/Object;
+Landroid/util/ArraySet;-><init>()V
+Lcom/android/internal/util/XmlUtils;->readBooleanAttribute(Lorg/xmlpull/v1/XmlPullParser;Ljava/lang/String;Z)Z
+Landroid/util/ArrayMap$1;->colGetEntry(II)Ljava/lang/Object;
+Landroid/util/MapCollections$ArrayIterator;->next()Ljava/lang/Object;
+Landroid/content/pm/PackageParserCacheHelper$ReadHelper;->readString(Landroid/os/Parcel;)Ljava/lang/String;
+Landroid/util/ArraySet;->indexOf(Ljava/lang/Object;)I
+Landroid/util/MapCollections$MapIterator;->hasNext()Z
+Landroid/os/Parcel;->readStringList(Ljava/util/List;)V
+Landroid/content/pm/Signature;->equals(Ljava/lang/Object;)Z
+Lcom/android/internal/util/ArrayUtils;->indexOf([Ljava/lang/Object;Ljava/lang/Object;)I
+Landroid/os/Parcel;->readParcelableList(Ljava/util/List;Ljava/lang/ClassLoader;)Ljava/util/List;
+Landroid/os/Parcel;->readStringArray()[Ljava/lang/String;
+Landroid/content/pm/PackageParser$SigningDetails;->hasCertificateInternal(Landroid/content/pm/Signature;I)Z
+Landroid/content/pm/PackageParser$SigningDetails;->hasPastSigningCertificates()Z
+Landroid/util/MapCollections$MapIterator;->getValue()Ljava/lang/Object;
+Landroid/content/pm/PackageParser$Package;->fixupOwner(Ljava/util/List;)V
+Landroid/util/MapCollections$MapIterator;->next()Ljava/lang/Object;
+Landroid/util/MapCollections$MapIterator;->next()Ljava/util/Map$Entry;
+Landroid/util/MapCollections$MapIterator;->getKey()Ljava/lang/Object;
+Landroid/content/pm/Signature;->areExactMatch([Landroid/content/pm/Signature;[Landroid/content/pm/Signature;)Z
+Lcom/android/internal/util/ArrayUtils;->containsAll([Ljava/lang/Object;[Ljava/lang/Object;)Z
+Lcom/android/internal/util/ArrayUtils;->contains([Ljava/lang/Object;Ljava/lang/Object;)Z
+Landroid/content/pm/PackageParser$SigningDetails;->hasCertificate(Landroid/content/pm/Signature;)Z
+Landroid/util/ArrayMap;->putAll(Ljava/util/Map;)V
+Landroid/os/Parcel;->createStringArrayList()Ljava/util/ArrayList;
+Landroid/content/pm/PackageParser$Package;->internStringArrayList(Ljava/util/List;)V
+Lcom/android/internal/util/ArrayUtils;->contains(Ljava/util/Collection;Ljava/lang/Object;)Z
+Landroid/util/ArraySet;->size()I
+Landroid/util/SparseArray;->keyAt(I)I
+Landroid/content/pm/PackageParser;->isApkFile(Ljava/io/File;)Z
+Landroid/content/pm/PackageParser;->isApkPath(Ljava/lang/String;)Z
+Landroid/os/Parcel;->readParcelableCreator(Ljava/lang/ClassLoader;)Landroid/os/Parcelable$Creator;
+Landroid/os/Parcel;->readParcelable(Ljava/lang/ClassLoader;)Landroid/os/Parcelable;
Landroid/os/Parcel;->readBundle()Landroid/os/Bundle;
Landroid/os/Parcel;->readBundle(Ljava/lang/ClassLoader;)Landroid/os/Bundle;
-Landroid/content/res/Resources;->getString(I)Ljava/lang/String;
-Landroid/content/res/Resources;->getString(I[Ljava/lang/Object;)Ljava/lang/String;
-Landroid/content/res/Resources;->getStringArray(I)[Ljava/lang/String;
-Landroid/os/ThreadLocalWorkSource;->setUid(I)J
-Landroid/content/pm/PackageParser;->parseClusterPackage(Ljava/io/File;I)Landroid/content/pm/PackageParser$Package;
-Landroid/content/pm/PackageParser;->parseClusterPackageLite(Ljava/io/File;I)Landroid/content/pm/PackageParser$PackageLite;
-Landroid/content/pm/split/DefaultSplitAssetLoader;->getBaseAssetManager()Landroid/content/res/AssetManager;
-Landroid/content/pm/PackageParser;->parseBaseApk(Ljava/io/File;Landroid/content/res/AssetManager;I)Landroid/content/pm/PackageParser$Package;
-Landroid/content/pm/PackageParser;->parseBaseApk(Ljava/lang/String;Landroid/content/res/Resources;Landroid/content/res/XmlResourceParser;I[Ljava/lang/String;)Landroid/content/pm/PackageParser$Package;
-Landroid/content/pm/PackageParser;->parseBaseApkCommon(Landroid/content/pm/PackageParser$Package;Ljava/util/Set;Landroid/content/res/Resources;Landroid/content/res/XmlResourceParser;I[Ljava/lang/String;)Landroid/content/pm/PackageParser$Package;
-Landroid/content/pm/PackageParser;->cacheResult(Ljava/io/File;ILandroid/content/pm/PackageParser$Package;)V
-Landroid/content/pm/PackageParser;->parseMonolithicPackage(Ljava/io/File;I)Landroid/content/pm/PackageParser$Package;
-Landroid/content/pm/PackageParser;->parseMonolithicPackageLite(Ljava/io/File;I)Landroid/content/pm/PackageParser$PackageLite;
-Landroid/content/pm/PackageParser;->parseApkLite(Ljava/io/File;I)Landroid/content/pm/PackageParser$ApkLite;
-Landroid/content/pm/PackageParser;->parseApkLite(Ljava/lang/String;Lorg/xmlpull/v1/XmlPullParser;Landroid/util/AttributeSet;Landroid/content/pm/PackageParser$SigningDetails;)Landroid/content/pm/PackageParser$ApkLite;
-Landroid/content/pm/PackageParser;->parseApkLiteInner(Ljava/io/File;Ljava/io/FileDescriptor;Ljava/lang/String;I)Landroid/content/pm/PackageParser$ApkLite;
-Landroid/content/pm/PackageParser;->toCacheEntry(Landroid/content/pm/PackageParser$Package;)[B
-Landroid/content/pm/PackageParser;->parseBaseApplication(Landroid/content/pm/PackageParser$Package;Landroid/content/res/Resources;Landroid/content/res/XmlResourceParser;I[Ljava/lang/String;)Z
-Landroid/os/Parcel;->writeParcelable(Landroid/os/Parcelable;I)V
-Landroid/os/Parcel;->writeParcelableArray([Landroid/os/Parcelable;I)V
-Landroid/os/Parcel;->writeParcelableCreator(Landroid/os/Parcelable;)V
-Landroid/os/Parcel;->writeParcelableList(Ljava/util/List;I)V
-Landroid/content/pm/PackageParser$Package;->writeToParcel(Landroid/os/Parcel;I)V
-Landroid/content/res/Resources;->obtainAttributes(Landroid/util/AttributeSet;[I)Landroid/content/res/TypedArray;
-Landroid/content/res/Resources;->obtainAttributes(Landroid/content/res/Resources;Landroid/content/res/Resources$Theme;Landroid/util/AttributeSet;[I)Landroid/content/res/TypedArray;
-Landroid/content/pm/split/DefaultSplitAssetLoader;->close()V
-Landroid/content/res/AssetManager;->openXmlResourceParser(ILjava/lang/String;)Landroid/content/res/XmlResourceParser;
-Landroid/content/res/AssetManager;->close()V
-Landroid/content/res/AssetManager;->openXmlBlockAsset(ILjava/lang/String;)Landroid/content/res/XmlBlock;
-Landroid/content/pm/PackageParser;->generateAppDetailsHiddenActivity(Landroid/content/pm/PackageParser$Package;I[Ljava/lang/String;Z)Landroid/content/pm/PackageParser$Activity;
-Landroid/content/pm/split/DefaultSplitAssetLoader;->loadApkAssets(Ljava/lang/String;I)Landroid/content/res/ApkAssets;
-Landroid/content/pm/PackageParser$Activity;->writeToParcel(Landroid/os/Parcel;I)V
-Landroid/os/FileUtils;->trimFilename(Ljava/lang/StringBuilder;I)V
-Landroid/content/res/ApkAssets;->openXml(Ljava/lang/String;)Landroid/content/res/XmlResourceParser;
-Landroid/content/res/Configuration;->setLocales(Landroid/os/LocaleList;)V
-Landroid/content/pm/PackageParser;->buildTaskAffinityName(Ljava/lang/String;Ljava/lang/String;Ljava/lang/CharSequence;[Ljava/lang/String;)Ljava/lang/String;
-Landroid/content/res/AssetManager;->retrieveAttributes(Landroid/content/res/XmlBlock$Parser;[I[I[I)Z
-Landroid/content/pm/PackageParser;->buildCompoundName(Ljava/lang/String;Ljava/lang/CharSequence;Ljava/lang/String;[Ljava/lang/String;)Ljava/lang/String;
-Landroid/content/pm/ActivityInfo;->writeToParcel(Landroid/os/Parcel;I)V
-Landroid/content/res/XmlBlock$Parser;->close()V
-Landroid/content/pm/PackageParser;->validateName(Ljava/lang/String;ZZ)Ljava/lang/String;
-Landroid/util/ArraySet;->equals(Ljava/lang/Object;)Z
-Landroid/content/pm/PackageItemInfo;->writeToParcel(Landroid/os/Parcel;I)V
-Landroid/content/pm/PackageParserCacheHelper$WriteHelper;->finishAndUninstall()V
-Landroid/content/res/TypedArray;->loadStringValueAt(I)Ljava/lang/CharSequence;
-Landroid/content/pm/ApplicationInfo;->writeToParcel(Landroid/os/Parcel;I)V
-Landroid/os/FileUtils;->isValidExtFilename(Ljava/lang/String;)Z
-Landroid/content/res/AssetManager;->findCookieForPath(Ljava/lang/String;)I
-Landroid/content/res/TypedArray;->getNonConfigurationString(II)Ljava/lang/String;
-Landroid/content/res/TypedArray;->peekValue(I)Landroid/util/TypedValue;
-Landroid/app/ActivityThread;->attach(ZJ)V
-Landroid/content/res/TypedArray;->getValueAt(ILandroid/util/TypedValue;)Z
-Landroid/content/res/XmlBlock$Parser;->getAttributeName(I)Ljava/lang/String;
-Landroid/content/res/XmlBlock$Parser;->getAttributeNameResource(I)I
-Landroid/content/pm/PackageParser$ApkLite;-><init>(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZLjava/lang/String;Ljava/lang/String;ZIIIILjava/util/List;Landroid/content/pm/PackageParser$SigningDetails;ZZZZZZZII)V
-Landroid/app/ResourcesManager;->createAssetManager(Landroid/content/res/ResourcesKey;)Landroid/content/res/AssetManager;
-Landroid/content/res/AssetManager$Builder;->build()Landroid/content/res/AssetManager;
-Landroid/os/FileUtils;->deleteContents(Ljava/io/File;)Z
-Landroid/os/FileUtils;->deleteContentsAndDir(Ljava/io/File;)Z
-Landroid/content/res/ResourcesImpl;->adjustLanguageTag(Ljava/lang/String;)Ljava/lang/String;
-Landroid/sysprop/DisplayProperties;->tryParseBoolean(Ljava/lang/String;)Ljava/lang/Boolean;
-Landroid/content/pm/PackageParserCacheHelper$WriteHelper;-><init>(Landroid/os/Parcel;)V
-Landroid/content/pm/PackageParser$Package;->getLongVersionCode()J
-Lcom/android/internal/util/function/pooled/OmniFunction;->run()V
-Lcom/android/internal/util/function/pooled/PooledLambdaImpl;->invoke(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-Landroid/os/SystemProperties;->get(Ljava/lang/String;)Ljava/lang/String;
-Landroid/os/SystemProperties;->get(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
-Landroid/os/SystemProperties;->getInt(Ljava/lang/String;I)I
-Landroid/os/SystemProperties;->getLong(Ljava/lang/String;J)J
-Landroid/content/res/ThemedResourceCache;->onConfigurationChange(I)V
-Landroid/content/res/TypedArray;->recycle()V
-Landroid/content/res/Configuration;->fixUpLocaleList()V
-Landroid/content/res/XmlBlock;->newParser(I)Landroid/content/res/XmlResourceParser;
-Landroid/content/pm/ComponentInfo;->writeToParcel(Landroid/os/Parcel;I)V
-Landroid/content/res/ApkAssets;->getAssetPath()Ljava/lang/String;
-Landroid/util/MapCollections$MapIterator;->next()Ljava/lang/Object;
-Landroid/content/res/ResourcesImpl;->flushLayoutCache()V
-Landroid/os/FileUtils;->buildValidExtFilename(Ljava/lang/String;)Ljava/lang/String;
-Landroid/content/res/ApkAssets;->getStringFromPool(I)Ljava/lang/CharSequence;
-Landroid/content/pm/Signature;->equals(Ljava/lang/Object;)Z
-Landroid/content/pm/PackageUserState;->equals(Ljava/lang/Object;)Z
-Landroid/util/ArrayMap$1;->colGetEntry(II)Ljava/lang/Object;
-Lcom/android/internal/os/BackgroundThread;->ensureThreadLocked()V
-Landroid/app/ActivityThread;-><init>()V
-Landroid/app/ActivityThread;->getSystemContext()Landroid/app/ContextImpl;
-Landroid/app/ContextImpl;->createSystemContext(Landroid/app/ActivityThread;)Landroid/app/ContextImpl;
-Landroid/app/ContextImpl;-><init>(Landroid/app/ContextImpl;Landroid/app/ActivityThread;Landroid/app/LoadedApk;Ljava/lang/String;Landroid/os/IBinder;Landroid/os/UserHandle;ILjava/lang/ClassLoader;Ljava/lang/String;)V
-Landroid/app/ResourcesManager;->getDisplayMetrics()Landroid/util/DisplayMetrics;
-Landroid/app/ResourcesManager;->getDisplayMetrics(ILandroid/view/DisplayAdjustments;)Landroid/util/DisplayMetrics;
-Landroid/content/pm/PackageParser$Package;->setApplicationVolumeUuid(Ljava/lang/String;)V
-Landroid/content/pm/AndroidHidlUpdater;->updatePackage(Landroid/content/pm/PackageParser$Package;)V
-Landroid/content/res/ApkAssets;->close()V
-Landroid/content/res/XmlBlock$Parser;->getAttributeBooleanValue(IZ)Z
-Landroid/content/res/XmlBlock$Parser;->getAttributeBooleanValue(Ljava/lang/String;Ljava/lang/String;Z)Z
-Landroid/content/pm/PackageParser;->setMaxAspectRatio(Landroid/content/pm/PackageParser$Package;)V
-Landroid/content/pm/PackageParserCacheHelper$WriteHelper;->writeString(Landroid/os/Parcel;Ljava/lang/String;)V
-Landroid/os/Parcel;->writeTypedList(Ljava/util/List;)V
-Landroid/os/Parcel;->writeTypedList(Ljava/util/List;I)V
-Landroid/content/res/Configuration;->getLocales()Landroid/os/LocaleList;
-Landroid/view/DisplayEventReceiver;-><init>(Landroid/os/Looper;I)V
-Lcom/android/internal/util/function/pooled/PooledLambdaImpl;->doInvoke()Ljava/lang/Object;
-Landroid/content/pm/PackageSharedLibraryUpdater;->prefixImplicitDependency(Landroid/content/pm/PackageParser$Package;Ljava/lang/String;Ljava/lang/String;)V
-Landroid/util/MapCollections$MapIterator;->getKey()Ljava/lang/Object;
+Landroid/text/TextUtils$1;->createFromParcel(Landroid/os/Parcel;)Ljava/lang/Object;
+Landroid/text/TextUtils$1;->createFromParcel(Landroid/os/Parcel;)Ljava/lang/CharSequence;
+Landroid/content/pm/PackageItemInfo;-><init>(Landroid/os/Parcel;)V
+Landroid/content/pm/PackageParser$Component;->createIntentsList(Landroid/os/Parcel;)Ljava/util/ArrayList;
+Landroid/content/pm/PackageParser$Component;-><init>(Landroid/os/Parcel;)V
+Landroid/content/pm/PackageParser$Permission$1;->createFromParcel(Landroid/os/Parcel;)Ljava/lang/Object;
+Landroid/content/pm/PackageParser$Permission$1;->createFromParcel(Landroid/os/Parcel;)Landroid/content/pm/PackageParser$Permission;
+Landroid/content/pm/PackageParser$Permission;-><init>(Landroid/os/Parcel;Landroid/content/pm/PackageParser$1;)V
+Landroid/content/pm/PackageParser$Permission;-><init>(Landroid/os/Parcel;)V
+Landroid/content/pm/PermissionInfo$1;->createFromParcel(Landroid/os/Parcel;)Ljava/lang/Object;
+Landroid/content/pm/PermissionInfo$1;->createFromParcel(Landroid/os/Parcel;)Landroid/content/pm/PermissionInfo;
+Landroid/content/pm/PermissionInfo;-><init>(Landroid/os/Parcel;Landroid/content/pm/PermissionInfo$1;)V
+Landroid/content/pm/PermissionInfo;-><init>(Landroid/os/Parcel;)V
+Landroid/os/Parcel;->readBoolean()Z
+Landroid/util/ArrayMap;->indexOfNull()I
+Landroid/util/MapCollections$ArrayIterator;-><init>(Landroid/util/MapCollections;I)V
+Landroid/util/ArrayMap$1;->colGetSize()I
+Landroid/util/ArrayMap;->getCollection()Landroid/util/MapCollections;
+Landroid/util/MapCollections;->getValues()Ljava/util/Collection;
Landroid/util/MapCollections$ValuesCollection;->iterator()Ljava/util/Iterator;
-Lcom/android/internal/os/BatteryStatsImpl$SystemClocks;->elapsedRealtime()J
-Landroid/app/LoadedApk;->makeApplication(ZLandroid/app/Instrumentation;)Landroid/app/Application;
-Landroid/content/pm/IntentFilterVerificationInfo;->getIntFromXml(Lorg/xmlpull/v1/XmlPullParser;Ljava/lang/String;I)I
-Landroid/content/res/ResourcesImpl;->calcConfigChanges(Landroid/content/res/Configuration;)I
-Landroid/content/pm/PackageBackwardCompatibility$AndroidTestRunnerSplitUpdater;->updatePackage(Landroid/content/pm/PackageParser$Package;)V
-Landroid/util/SparseArray;->valueAt(I)Ljava/lang/Object;
-Landroid/util/ArraySet;->ensureCapacity(I)V
-Landroid/os/storage/StorageManager;->convert(Ljava/lang/String;)Ljava/util/UUID;
-Landroid/os/storage/StorageManager;->convert(Ljava/util/UUID;)Ljava/lang/String;
-Landroid/content/pm/PackageParser;->checkOverlayRequiredSystemProperty(Ljava/lang/String;Ljava/lang/String;)Z
-Landroid/content/res/ThemedResourceCache;->prune(I)Z
-Landroid/content/res/ThemedResourceCache;->pruneEntriesLocked(Landroid/util/LongSparseArray;I)Z
-Landroid/util/Pools$SynchronizedPool;->acquire()Ljava/lang/Object;
-Landroid/content/res/XmlBlock$Parser;->getAttributeCount()I
-Landroid/content/pm/PackageParser;->parseMetaData(Landroid/content/res/Resources;Landroid/content/res/XmlResourceParser;Landroid/os/Bundle;[Ljava/lang/String;)Landroid/os/Bundle;
-Landroid/content/res/Resources;->getDisplayMetrics()Landroid/util/DisplayMetrics;
-Landroid/text/TextUtils;->writeToParcel(Ljava/lang/CharSequence;Landroid/os/Parcel;I)V
-Landroid/view/DisplayAdjustments;->setCompatibilityInfo(Landroid/content/res/CompatibilityInfo;)V
-Landroid/content/res/CompatibilityInfo;->applyToDisplayMetrics(Landroid/util/DisplayMetrics;)V
-Landroid/content/res/TypedArray;->getString(I)Ljava/lang/String;
-Lcom/android/internal/os/BatteryStatsImpl$SamplingTimer;->getUpdateVersion()I
-Landroid/os/ResultReceiver;->send(ILandroid/os/Bundle;)V
-Lcom/android/internal/os/ProcessCpuTracker;->getCpuTimeForPid(I)J
-Landroid/os/FileUtils;->contains(Ljava/io/File;Ljava/io/File;)Z
-Landroid/os/FileUtils;->contains(Ljava/lang/String;Ljava/lang/String;)Z
-Landroid/content/pm/PackageParser$SigningDetails;->checkCapability(Landroid/content/pm/PackageParser$SigningDetails;I)Z
-Landroid/util/MapCollections$MapIterator;->getValue()Ljava/lang/Object;
-Landroid/os/BinderProxy$ProxyMap;->get(J)Landroid/os/BinderProxy;
-Landroid/util/TimingsTraceLog;-><init>(Ljava/lang/String;J)V
-Landroid/os/PowerManager;->newWakeLock(ILjava/lang/String;)Landroid/os/PowerManager$WakeLock;
-Landroid/content/ComponentName;->hashCode()I
-Landroid/util/MapCollections$ArrayIterator;->hasNext()Z
-Landroid/app/IActivityTaskManager$Stub;-><init>()V
-Lcom/android/internal/os/ProcessCpuTracker;-><init>(Z)V
-Lcom/android/internal/util/RingBuffer;-><init>(Ljava/lang/Class;I)V
-Lcom/android/server/LocalServices;->getService(Ljava/lang/Class;)Ljava/lang/Object;
-Lcom/android/internal/util/XmlUtils;->readStringAttribute(Lorg/xmlpull/v1/XmlPullParser;Ljava/lang/String;)Ljava/lang/String;
-Lcom/android/internal/os/BatteryStatsImpl;->setPowerProfileLocked(Lcom/android/internal/os/PowerProfile;)V
-Lcom/android/internal/os/BatteryStatsImpl;->readDailyStatsLocked()V
-Lcom/android/internal/widget/LockPatternUtils;-><init>(Landroid/content/Context;)V
-Landroid/text/SpannableStringBuilder;->replace(IILjava/lang/CharSequence;)Landroid/text/Editable;
-Landroid/text/SpannableStringBuilder;->replace(IILjava/lang/CharSequence;)Landroid/text/SpannableStringBuilder;
-Landroid/text/SpannableStringBuilder;->replace(IILjava/lang/CharSequence;II)Landroid/text/SpannableStringBuilder;
-Landroid/content/res/Resources;->newTheme()Landroid/content/res/Resources$Theme;
-Landroid/os/Parcel;->obtain()Landroid/os/Parcel;
-Landroid/os/Parcel;->obtain(J)Landroid/os/Parcel;
-Landroid/content/res/Configuration;->updateFrom(Landroid/content/res/Configuration;)I
-Landroid/app/ContextImpl;->createAppContext(Landroid/app/ActivityThread;Landroid/app/LoadedApk;)Landroid/app/ContextImpl;
-Landroid/app/ContextImpl;->createAppContext(Landroid/app/ActivityThread;Landroid/app/LoadedApk;Ljava/lang/String;)Landroid/app/ContextImpl;
-Landroid/util/SparseArray;->clear()V
-Landroid/util/ArrayMap;->remove(Ljava/lang/Object;)Ljava/lang/Object;
-Landroid/util/ArrayMap;->removeAt(I)Ljava/lang/Object;
-Landroid/os/Parcel;->writeBundle(Landroid/os/Bundle;)V
-Landroid/content/pm/PackageParser;->hasDomainURLs(Landroid/content/pm/PackageParser$Package;)Z
-Landroid/util/Pools$SynchronizedPool;->release(Ljava/lang/Object;)Z
+Landroid/util/ArrayMap;->values()Ljava/util/Collection;
+Landroid/os/Parcel;->readFloat()F
+Landroid/content/pm/PackageBackwardCompatibility;->updatePackage(Landroid/content/pm/PackageParser$Package;)V
Landroid/os/Parcel;->setDataPosition(I)V
-Landroid/os/LocaleList;->getDefault()Landroid/os/LocaleList;
-Landroid/content/res/ConfigurationBoundResourceCache;->onConfigurationChange(I)V
+Landroid/content/pm/PackageParser$Activity;-><init>(Landroid/os/Parcel;)V
+Landroid/content/pm/ComponentInfo;-><init>(Landroid/os/Parcel;)V
+Landroid/util/SparseArray;->clear()V
+Lcom/android/internal/util/ArrayUtils;->remove(Ljava/util/ArrayList;Ljava/lang/Object;)Ljava/util/ArrayList;
+Landroid/content/pm/PackageParser$Activity$1;->createFromParcel(Landroid/os/Parcel;)Ljava/lang/Object;
+Landroid/content/pm/PackageParser$Activity$1;->createFromParcel(Landroid/os/Parcel;)Landroid/content/pm/PackageParser$Activity;
+Landroid/content/pm/PackageParser$Activity;-><init>(Landroid/os/Parcel;Landroid/content/pm/PackageParser$1;)V
+Landroid/content/pm/ActivityInfo$1;->createFromParcel(Landroid/os/Parcel;)Landroid/content/pm/ActivityInfo;
+Landroid/content/pm/ActivityInfo;-><init>(Landroid/os/Parcel;Landroid/content/pm/ActivityInfo$1;)V
+Landroid/content/pm/ActivityInfo;-><init>(Landroid/os/Parcel;)V
+Landroid/content/pm/ActivityInfo$1;->createFromParcel(Landroid/os/Parcel;)Ljava/lang/Object;
+Landroid/content/ComponentName;->hashCode()I
+Landroid/content/pm/PackageParser$Component;->getComponentName()Landroid/content/ComponentName;
+Landroid/os/Parcel;->createIntArray()[I
+Landroid/content/ComponentName;-><init>(Ljava/lang/String;Ljava/lang/String;)V
+Landroid/util/ArraySet;->contains(Ljava/lang/Object;)Z
+Landroid/os/Parcel;->createTypedArrayList(Landroid/os/Parcelable$Creator;)Ljava/util/ArrayList;
+Landroid/os/Parcel;->obtain()Landroid/os/Parcel;
+Landroid/os/UserHandle;->getAppId(I)I
+Landroid/util/ArrayMap;->clear()V
+Landroid/util/ArraySet;->remove(Ljava/lang/Object;)Z
+Landroid/content/IntentFilter;->actionsIterator()Ljava/util/Iterator;
+Landroid/content/IntentFilter;-><init>(Landroid/os/Parcel;)V
+Landroid/os/Parcel;->updateNativeSize(J)V
+Landroid/content/IntentFilter;->setAutoVerify(Z)V
+Landroid/content/IntentFilter;->setVisibilityToInstantApp(I)V
+Landroid/os/Parcel;->readCharSequence()Ljava/lang/CharSequence;
+Landroid/content/pm/PackageParser$IntentInfo;-><init>(Landroid/os/Parcel;)V
+Landroid/os/SystemProperties;->getBoolean(Ljava/lang/String;Z)Z
+Landroid/os/Parcel;->recycle()V
+Landroid/util/ArraySet;->valueAt(I)Ljava/lang/Object;
+Landroid/util/ArraySet;->valueAtUnchecked(I)Ljava/lang/Object;
+Landroid/content/pm/PackageParser$Package;->isPrivileged()Z
+Landroid/content/pm/ApplicationInfo;->isPrivilegedApp()Z
+Landroid/content/IntentFilter;->schemesIterator()Ljava/util/Iterator;
+Landroid/content/IntentFilter;->typesIterator()Ljava/util/Iterator;
+Landroid/content/IntentFilter;->debugCheck()Z
+Landroid/util/ArrayMap;-><init>(I)V
+Landroid/util/ArrayMap;->containsKey(Ljava/lang/Object;)Z
+Landroid/content/IntentFilter;->getOrder()I
+Landroid/content/pm/PackageSharedLibraryUpdater;->isLibraryPresent(Ljava/util/ArrayList;Ljava/util/ArrayList;Ljava/lang/String;)Z
+Landroid/content/pm/PackageParser$Package;->getLongVersionCode()J
+Landroid/content/pm/PackageInfo;->composeLongVersionCode(II)J
+Lcom/android/internal/util/ArrayUtils;->isEmpty(Ljava/util/Collection;)Z
+Landroid/content/pm/ApplicationInfo;->isStaticSharedLibrary()Z
+Landroid/content/pm/ApplicationInfo;->getCodePath()Ljava/lang/String;
+Landroid/content/pm/ApplicationInfo;->getResourcePath()Ljava/lang/String;
+Landroid/content/pm/ApplicationInfo;->isSystemApp()Z
+Landroid/util/ArraySet;->equals(Ljava/lang/Object;)Z
+Landroid/os/Environment;->getDataDirectory(Ljava/lang/String;)Ljava/io/File;
+Landroid/content/pm/PackageParser$ActivityIntentInfo;-><init>(Landroid/os/Parcel;)V
+Landroid/content/pm/PackageSharedLibraryUpdater;->prefixImplicitDependency(Landroid/content/pm/PackageParser$Package;Ljava/lang/String;Ljava/lang/String;)V
+Landroid/content/pm/PackageParser$Service;-><init>(Landroid/os/Parcel;)V
+Landroid/content/pm/PackageSharedLibraryUpdater;->removeLibrary(Landroid/content/pm/PackageParser$Package;Ljava/lang/String;)V
+Landroid/content/pm/PackageParser$Service$1;->createFromParcel(Landroid/os/Parcel;)Landroid/content/pm/PackageParser$Service;
+Landroid/content/pm/ServiceInfo;-><init>(Landroid/os/Parcel;Landroid/content/pm/ServiceInfo$1;)V
+Landroid/content/pm/ServiceInfo;-><init>(Landroid/os/Parcel;)V
+Landroid/content/pm/PackageParser$Service$1;->createFromParcel(Landroid/os/Parcel;)Ljava/lang/Object;
+Landroid/content/pm/PackageParser$Service;-><init>(Landroid/os/Parcel;Landroid/content/pm/PackageParser$1;)V
+Landroid/content/pm/ServiceInfo$1;->createFromParcel(Landroid/os/Parcel;)Landroid/content/pm/ServiceInfo;
+Landroid/content/pm/ServiceInfo$1;->createFromParcel(Landroid/os/Parcel;)Ljava/lang/Object;
+Landroid/os/Parcel;->readArrayMapInternal(Landroid/util/ArrayMap;ILjava/lang/ClassLoader;)V
+Landroid/os/Parcel;->readValue(Ljava/lang/ClassLoader;)Ljava/lang/Object;
+Landroid/util/ArrayMap;->append(Ljava/lang/Object;Ljava/lang/Object;)V
+Landroid/util/ArrayMap;->validate()V
+Landroid/content/pm/PackageUserState;->equals(Ljava/lang/Object;)Z
+Landroid/content/IntentFilter;->getPriority()I
+Landroid/os/Parcel;->createTypedArray(Landroid/os/Parcelable$Creator;)[Ljava/lang/Object;
+Landroid/os/BaseBundle;->readFromParcelInner(Landroid/os/Parcel;I)V
+Landroid/os/Parcel;->hasReadWriteHelper()Z
+Landroid/os/BaseBundle;->initializeFromParcelLocked(Landroid/os/Parcel;ZZ)V
+Landroid/os/BaseBundle;->isEmptyParcel(Landroid/os/Parcel;)Z
+Landroid/content/pm/PackageParser$ServiceIntentInfo;-><init>(Landroid/os/Parcel;)V
+Landroid/content/pm/PackageParser$Provider;-><init>(Landroid/os/Parcel;)V
+Landroid/os/Parcel;->freeBuffer()V
+Landroid/content/IntentFilter$AuthorityEntry;-><init>(Landroid/os/Parcel;)V
+Landroid/content/pm/PackageParser$Provider$1;->createFromParcel(Landroid/os/Parcel;)Ljava/lang/Object;
+Landroid/content/pm/PackageParser$Provider$1;->createFromParcel(Landroid/os/Parcel;)Landroid/content/pm/PackageParser$Provider;
+Landroid/content/pm/PackageParser$Provider;-><init>(Landroid/os/Parcel;Landroid/content/pm/PackageParser$1;)V
+Landroid/content/pm/ProviderInfo$1;->createFromParcel(Landroid/os/Parcel;)Ljava/lang/Object;
+Landroid/content/pm/ProviderInfo$1;->createFromParcel(Landroid/os/Parcel;)Landroid/content/pm/ProviderInfo;
+Landroid/content/pm/ProviderInfo;-><init>(Landroid/os/Parcel;Landroid/content/pm/ProviderInfo$1;)V
+Landroid/content/pm/ProviderInfo;-><init>(Landroid/os/Parcel;)V
+Landroid/util/MapCollections;->getEntrySet()Ljava/util/Set;
+Landroid/content/pm/PackageParser$SigningDetails;->checkCapability(Landroid/content/pm/PackageParser$SigningDetails;I)Z
+Landroid/content/IntentFilter;->countActions()I
+Landroid/content/IntentFilter;->countCategories()I
+Landroid/content/IntentFilter;->getAction(I)Ljava/lang/String;
+Landroid/content/IntentFilter;->hasAction(Ljava/lang/String;)Z
+Landroid/content/pm/PackageParser$SigningDetails;->hasCertificate(Landroid/content/pm/Signature;I)Z
+Landroid/content/pm/PackageItemInfo;-><init>()V
+Landroid/util/DisplayMetrics;-><init>()V
+Landroid/content/pm/FeatureInfo$1;->createFromParcel(Landroid/os/Parcel;)Ljava/lang/Object;
+Landroid/content/pm/FeatureInfo$1;->createFromParcel(Landroid/os/Parcel;)Landroid/content/pm/FeatureInfo;
+Landroid/content/pm/FeatureInfo;-><init>(Landroid/os/Parcel;Landroid/content/pm/FeatureInfo$1;)V
+Landroid/content/pm/FeatureInfo;-><init>(Landroid/os/Parcel;)V
Landroid/util/DisplayMetrics;->setToDefaults()V
-Landroid/content/pm/PackageParser;->computeMinSdkVersion(ILjava/lang/String;I[Ljava/lang/String;[Ljava/lang/String;)I
-Lcom/android/internal/os/ProcessCpuTracker;->onMeasureProcessName(Ljava/lang/String;)I
-Lcom/android/server/SystemConfig$SharedLibraryEntry;-><init>(Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;)V
+Landroid/os/Parcel;->unmarshall([BII)V
+Landroid/content/pm/PackageParser$Package;-><init>(Landroid/os/Parcel;)V
+Landroid/content/pm/ApplicationInfo;-><init>()V
+Landroid/content/pm/PackageParser;->setCallback(Landroid/content/pm/PackageParser$Callback;)V
+Landroid/content/pm/PackageParser;->getCachedResult(Ljava/io/File;I)Landroid/content/pm/PackageParser$Package;
+Landroid/os/Parcel;->setReadWriteHelper(Landroid/os/Parcel$ReadWriteHelper;)V
+Landroid/content/pm/PackageParser;->setSeparateProcesses([Ljava/lang/String;)V
+Landroid/content/pm/PackageParser;->setOnlyCoreApps(Z)V
+Landroid/content/pm/PackageParser;->setDisplayMetrics(Landroid/util/DisplayMetrics;)V
+Landroid/content/pm/PackageParser;->setCacheDir(Ljava/io/File;)V
+Landroid/content/pm/PackageParser;->parsePackage(Ljava/io/File;IZ)Landroid/content/pm/PackageParser$Package;
+Landroid/content/pm/PackageParser;->getCacheKey(Ljava/io/File;I)Ljava/lang/String;
+Landroid/content/pm/PackageParser;-><init>()V
+Landroid/content/pm/PackageSharedLibraryUpdater;->prefixRequiredLibrary(Landroid/content/pm/PackageParser$Package;Ljava/lang/String;)V
+Landroid/content/pm/PackageSharedLibraryUpdater;->prefix(Ljava/util/ArrayList;Ljava/lang/Object;)Ljava/util/ArrayList;
+Landroid/content/pm/PackageParser$SigningDetails$1;->createFromParcel(Landroid/os/Parcel;)Ljava/lang/Object;
+Landroid/content/pm/PackageParser$SigningDetails$1;->createFromParcel(Landroid/os/Parcel;)Landroid/content/pm/PackageParser$SigningDetails;
+Landroid/os/Parcel;->readArraySet(Ljava/lang/ClassLoader;)Landroid/util/ArraySet;
+Landroid/content/pm/PackageParser$Package;->readKeySetMapping(Landroid/os/Parcel;)Landroid/util/ArrayMap;
+Landroid/os/Parcel;->createByteArray()[B
+Landroid/content/pm/ApplicationInfo$1;->createFromParcel(Landroid/os/Parcel;)Ljava/lang/Object;
+Landroid/content/pm/ApplicationInfo$1;->createFromParcel(Landroid/os/Parcel;)Landroid/content/pm/ApplicationInfo;
+Landroid/content/pm/ApplicationInfo;-><init>(Landroid/os/Parcel;Landroid/content/pm/ApplicationInfo$1;)V
+Landroid/content/pm/ApplicationInfo;-><init>(Landroid/os/Parcel;)V
+Landroid/util/ArraySet$1;->colGetEntry(II)Ljava/lang/Object;
+Landroid/content/IntentFilter;->getCategory(I)Ljava/lang/String;
+Landroid/content/IntentFilter;->hasCategory(Ljava/lang/String;)Z
+Landroid/content/pm/ApplicationInfo;->isUpdatedSystemApp()Z
+Landroid/content/IntentFilter;->countDataSchemes()I
+Landroid/content/IntentFilter;->countDataTypes()I
+Landroid/content/IntentFilter;->countDataAuthorities()I
+Landroid/content/pm/PackageParser$Package;->setApplicationVolumeUuid(Ljava/lang/String;)V
+Landroid/os/storage/StorageManager;->convert(Ljava/lang/String;)Ljava/util/UUID;
+Landroid/content/pm/PackageParser$Package;->setApplicationInfoCodePath(Ljava/lang/String;)V
+Landroid/content/pm/ApplicationInfo;->setCodePath(Ljava/lang/String;)V
+Landroid/content/pm/PackageParser$Package;->setApplicationInfoBaseCodePath(Ljava/lang/String;)V
+Landroid/content/pm/ApplicationInfo;->setBaseCodePath(Ljava/lang/String;)V
+Landroid/content/pm/PackageParser$Package;->setApplicationInfoSplitCodePaths([Ljava/lang/String;)V
+Landroid/content/pm/ApplicationInfo;->setSplitCodePaths([Ljava/lang/String;)V
+Landroid/content/pm/PackageParser$Package;->setApplicationInfoResourcePath(Ljava/lang/String;)V
+Landroid/content/pm/ApplicationInfo;->setResourcePath(Ljava/lang/String;)V
+Landroid/content/pm/PackageParser$Package;->setApplicationInfoBaseResourcePath(Ljava/lang/String;)V
+Landroid/content/pm/ApplicationInfo;->setBaseResourcePath(Ljava/lang/String;)V
+Landroid/content/pm/PackageParser$Package;->setApplicationInfoSplitResourcePaths([Ljava/lang/String;)V
+Landroid/content/pm/ApplicationInfo;->setSplitResourcePaths([Ljava/lang/String;)V
+Landroid/content/pm/AndroidHidlUpdater;->updatePackage(Landroid/content/pm/PackageParser$Package;)V
+Landroid/content/pm/PackageParser$Package;->getChildPackageNames()Ljava/util/List;
+Landroid/content/pm/SELinuxUtil;->assignSeinfoUser(Landroid/content/pm/PackageUserState;)Ljava/lang/String;
+Landroid/content/pm/ApplicationInfo;->initForUser(I)V
+Landroid/os/UserHandle;->getUid(II)I
+Landroid/os/Environment;->getDataUserDePackageDirectory(Ljava/lang/String;ILjava/lang/String;)Ljava/io/File;
+Landroid/os/Environment;->getDataUserDeDirectory(Ljava/lang/String;I)Ljava/io/File;
+Landroid/os/Environment;->getDataUserDeDirectory(Ljava/lang/String;)Ljava/io/File;
+Landroid/os/Environment;->getDataUserCePackageDirectory(Ljava/lang/String;ILjava/lang/String;)Ljava/io/File;
+Landroid/os/Environment;->getDataUserCeDirectory(Ljava/lang/String;I)Ljava/io/File;
+Landroid/os/Environment;->getDataUserCeDirectory(Ljava/lang/String;)Ljava/io/File;
+Landroid/content/pm/SharedLibraryInfo;->getPath()Ljava/lang/String;
+Landroid/content/pm/ApplicationInfo;->isInstantApp()Z
+Landroid/permission/PermissionManager$SplitPermissionInfo;->getNewPermissions()Ljava/util/List;
+Landroid/permission/PermissionManager$SplitPermissionInfo;->getSplitPermission()Ljava/lang/String;
+Landroid/content/pm/PackageParser$SigningDetails;->hasAncestorOrSelf(Landroid/content/pm/PackageParser$SigningDetails;)Z
+Landroid/content/pm/PackageParser$Package;->isVendor()Z
+Landroid/content/pm/ApplicationInfo;->isVendor()Z
+Landroid/util/ArraySet;->iterator()Ljava/util/Iterator;
+Landroid/util/ArraySet;->getCollection()Landroid/util/MapCollections;
Landroid/util/MapCollections;->getKeySet()Ljava/util/Set;
-Landroid/content/ComponentName;->unflattenFromString(Ljava/lang/String;)Landroid/content/ComponentName;
-Landroid/util/Slog;->e(Ljava/lang/String;Ljava/lang/String;)I
-Landroid/util/Slog;->e(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Throwable;)I
-Landroid/os/SynchronousResultReceiver;->awaitResult(J)Landroid/os/SynchronousResultReceiver$Result;
-Landroid/os/SynchronousResultReceiver;->onReceiveResult(ILandroid/os/Bundle;)V
-Landroid/view/SurfaceControl;->getHdrCapabilities(Landroid/os/IBinder;)Landroid/view/Display$HdrCapabilities;
+Landroid/util/MapCollections$KeySet;->iterator()Ljava/util/Iterator;
+Landroid/util/ArraySet$1;->colGetSize()I
+Lcom/android/server/SystemConfig;->getInstance()Lcom/android/server/SystemConfig;
+Landroid/content/pm/PackageParser$Package;->isProduct()Z
+Landroid/content/pm/ApplicationInfo;->isProduct()Z
+Landroid/content/pm/PackageParser$Package;->isSystem()Z
+Landroid/content/pm/PackageParser$Package;->isUpdatedSystemApp()Z
+Lcom/android/server/SystemConfig;->getProductPrivAppPermissions(Ljava/lang/String;)Landroid/util/ArraySet;
+Landroid/text/TextUtils;->equals(Ljava/lang/CharSequence;Ljava/lang/CharSequence;)Z
+Lcom/android/internal/util/FastXmlSerializer;->escapeAndAppendString(Ljava/lang/String;)V
+Lcom/android/internal/util/FastXmlSerializer;->append(Ljava/lang/String;II)V
+Lcom/android/internal/util/FastXmlSerializer;->append(Ljava/lang/String;)V
+Lcom/android/internal/util/FastXmlSerializer;->append(C)V
+Lcom/android/internal/util/FastXmlSerializer;->attribute(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Lorg/xmlpull/v1/XmlSerializer;
+Lcom/android/internal/util/FastXmlSerializer;->appendIndent(I)V
+Lcom/android/internal/util/FastXmlSerializer;->startTag(Ljava/lang/String;Ljava/lang/String;)Lorg/xmlpull/v1/XmlSerializer;
+Lcom/android/internal/util/FastXmlSerializer;->endTag(Ljava/lang/String;Ljava/lang/String;)Lorg/xmlpull/v1/XmlSerializer;
+Landroid/content/pm/Signature;->toChars([C[I)[C
+Landroid/content/pm/Signature;->hashCode()I
+Landroid/content/pm/IntentFilterVerificationInfo;->writeToXml(Lorg/xmlpull/v1/XmlSerializer;)V
+Landroid/util/ArrayMap;->entrySet()Ljava/util/Set;
+Landroid/util/MapCollections$EntrySet;->iterator()Ljava/util/Iterator;
+Landroid/util/MapCollections$MapIterator;-><init>(Landroid/util/MapCollections;)V
+Landroid/util/MapCollections$EntrySet;-><init>(Landroid/util/MapCollections;)V
+Lcom/android/internal/util/ArrayUtils;->isEmpty([Ljava/lang/Object;)Z
+Landroid/util/Base64$Encoder;->process([BIIZ)Z
+Landroid/os/FileUtils;->bytesToFile(Ljava/lang/String;[B)V
+Landroid/os/FileUtils;->$closeResource(Ljava/lang/Throwable;Ljava/lang/AutoCloseable;)V
+Landroid/util/ArraySet;->removeAt(I)Ljava/lang/Object;
+Landroid/util/ArraySet;->shouldShrink()Z
+Landroid/util/MapCollections;-><init>()V
+Landroid/content/IntentFilter;->getAutoVerify()Z
+Landroid/content/IntentFilter;->match(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Landroid/net/Uri;Ljava/util/Set;Ljava/lang/String;)I
+Landroid/content/IntentFilter;->matchAction(Ljava/lang/String;)Z
+Landroid/content/pm/ApplicationInfo;->setVersionCode(J)V
+Landroid/os/Process;->isIsolated(I)Z
+Landroid/content/pm/PackageUserState;->isAvailable(I)Z
+Landroid/content/pm/PackageParser;->checkUseInstalledOrHidden(ILandroid/content/pm/PackageUserState;Landroid/content/pm/ApplicationInfo;)Z
+Landroid/content/pm/PackageParser$Package;->isMatch(I)Z
+Landroid/content/pm/PackageParser;->copyNeeded(ILandroid/content/pm/PackageParser$Package;Landroid/content/pm/PackageUserState;Landroid/os/Bundle;I)Z
+Landroid/content/pm/PackageParser;->updateApplicationInfo(Landroid/content/pm/ApplicationInfo;ILandroid/content/pm/PackageUserState;)V
+Landroid/content/pm/PackageParser;->generateApplicationInfo(Landroid/content/pm/PackageParser$Package;ILandroid/content/pm/PackageUserState;I)Landroid/content/pm/ApplicationInfo;
+Landroid/content/pm/FallbackCategoryProvider;->getFallbackCategory(Ljava/lang/String;)I
+Landroid/os/storage/StorageManager;->isFileEncryptedNativeOnly()Z
+Landroid/os/storage/StorageManager;->isEncrypted()Z
+Landroid/content/pm/PackageParser;->generatePackageInfo(Landroid/content/pm/PackageParser$Package;[IIJJLjava/util/Set;Landroid/content/pm/PackageUserState;I)Landroid/content/pm/PackageInfo;
+Landroid/content/pm/PackageInfo;-><init>()V
+Landroid/os/Parcel;->writeInterfaceToken(Ljava/lang/String;)V
+Landroid/os/BinderProxy;->transact(ILandroid/os/Parcel;Landroid/os/Parcel;I)Z
+Landroid/os/Binder;->checkParcel(Landroid/os/IBinder;ILandroid/os/Parcel;Ljava/lang/String;)V
+Landroid/os/Binder;->isTracingEnabled()Z
+Landroid/os/Parcel;->readException()V
+Landroid/os/Parcel;->readExceptionCode()I
+Landroid/os/UserHandle;->getUserId(I)I
+Landroid/util/proto/ProtoInputStream;->fillBuffer()V
+Landroid/util/proto/ProtoInputStream;->getOffset()I
+Landroid/util/proto/ProtoStream;->getOffsetFromToken(J)I
+Landroid/util/proto/ProtoInputStream;->incOffset(I)V
+Landroid/util/proto/ProtoInputStream;->readVarint()J
+Landroid/util/proto/ProtoInputStream;->nextField()I
+Landroid/util/proto/ProtoInputStream;->readTag()V
+Landroid/util/proto/ProtoInputStream;->assertFreshData()V
+Landroid/util/proto/ProtoInputStream;->assertFieldNumber(J)V
+Landroid/util/proto/ProtoInputStream;->assertWireType(I)V
+Landroid/util/proto/ProtoInputStream;->getFieldNumber()I
+Landroid/util/proto/ProtoInputStream;->checkPacked(J)V
+Lcom/android/internal/util/ArrayUtils;->newUnpaddedIntArray(I)[I
+Landroid/util/proto/ProtoInputStream;->readLong(J)J
+Landroid/util/SparseIntArray;-><init>(I)V
+Landroid/util/SparseIntArray;-><init>()V
+Landroid/util/proto/ProtoInputStream;->readInt(J)I
+Landroid/util/proto/ProtoInputStream;->start(J)J
+Landroid/util/proto/ProtoStream;->makeToken(IZIII)J
+Landroid/util/proto/ProtoInputStream;->end(J)V
+Landroid/util/proto/ProtoInputStream;->readString(J)Ljava/lang/String;
+Landroid/util/proto/ProtoInputStream;->readRawString(I)Ljava/lang/String;
+Landroid/util/ArraySet;->addAll(Ljava/util/Collection;)Z
+Landroid/app/usage/UsageStats;-><init>()V
+Landroid/content/res/Configuration;->readFromProto(Landroid/util/proto/ProtoInputStream;J)V
+Landroid/util/proto/ProtoInputStream;->nextField(J)Z
+Lcom/android/internal/util/Preconditions;->checkNotNull(Ljava/lang/Object;)Ljava/lang/Object;
+Landroid/net/Uri;->access$300()Ljava/lang/String;
+Landroid/net/UriCodec;->appendDecoded(Ljava/lang/StringBuilder;Ljava/lang/String;ZLjava/nio/charset/Charset;Z)V
+Landroid/net/UriCodec;->flushDecodingByteAccumulator(Ljava/lang/StringBuilder;Ljava/nio/charset/CharsetDecoder;Ljava/nio/ByteBuffer;Z)V
+Landroid/net/Uri$PathPart;->getPathSegments()Landroid/net/Uri$PathSegments;
+Landroid/net/Uri$Part;->nonNull(Landroid/net/Uri$Part;)Landroid/net/Uri$Part;
+Landroid/net/Uri$HierarchicalUri;->getPathSegments()Ljava/util/List;
+Landroid/os/UserHandle;->getCallingUserId()I
+Lcom/android/internal/util/FastPrintWriter;->appendLocked(Ljava/lang/String;II)V
+Landroid/net/Uri;->decode(Ljava/lang/String;)Ljava/lang/String;
+Landroid/net/UriCodec;->decode(Ljava/lang/String;ZLjava/nio/charset/Charset;Z)Ljava/lang/String;
+Landroid/text/TextUtils;->safeIntern(Ljava/lang/String;)Ljava/lang/String;
+Landroid/view/animation/PathInterpolator;->initPath(Landroid/graphics/Path;)V
+Landroid/app/WindowConfiguration;->setAppBounds(Landroid/graphics/Rect;)V
+Landroid/app/WindowConfiguration;->setBounds(Landroid/graphics/Rect;)V
+Landroid/app/WindowConfiguration;->setWindowingMode(I)V
+Landroid/app/WindowConfiguration;->setActivityType(I)V
+Landroid/app/WindowConfiguration;->setAlwaysOnTop(I)V
+Landroid/app/WindowConfiguration;->setRotation(I)V
+Landroid/app/WindowConfiguration;->setDisplayWindowingMode(I)V
+Landroid/os/LocaleList;->isEmpty()Z
+Landroid/content/res/AssetManager;->getResourceValue(IILandroid/util/TypedValue;Z)Z
+Landroid/content/res/Configuration;->fixUpLocaleList()V
+Landroid/content/res/Resources;->obtainTempTypedValue()Landroid/util/TypedValue;
+Landroid/content/res/Resources;->releaseTempTypedValue(Landroid/util/TypedValue;)V
+Landroid/graphics/Rect;->setEmpty()V
+Landroid/net/UriCodec;->getNextCharacter(Ljava/lang/String;IILjava/lang/String;)C
+Landroid/net/UriCodec;->hexCharToValue(C)I
+Landroid/net/Uri$AbstractPart;->getDecoded()Ljava/lang/String;
+Landroid/net/Uri$PathSegments;->size()I
+Landroid/app/WindowConfiguration;->setToDefaults()V
+Lcom/android/internal/util/LineBreakBufferedWriter;->write(Ljava/lang/String;II)V
+Landroid/net/Uri;->encode(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
+Landroid/net/Uri;->isAllowed(CLjava/lang/String;)Z
+Landroid/os/BaseBundle;->unparcel()V
+Landroid/content/Intent;->getAction()Ljava/lang/String;
+Landroid/os/Process;->myUid()I
+Landroid/content/res/ResourcesImpl;->getValue(ILandroid/util/TypedValue;Z)V
+Landroid/graphics/Rect;->set(Landroid/graphics/Rect;)V
+Landroid/content/res/Configuration;->setTo(Landroid/content/res/Configuration;)V
+Landroid/app/WindowConfiguration;->setTo(Landroid/app/WindowConfiguration;)V
+Landroid/util/ArrayMap;->ensureCapacity(I)V
+Landroid/util/TypedValue;->complexToFloat(I)F
+Landroid/content/res/ThemedResourceCache;->pruneEntriesLocked(Landroid/util/LongSparseArray;I)Z
+Landroid/util/TypedValue;->applyDimension(IFLandroid/util/DisplayMetrics;)F
+Landroid/os/MessageQueue;->enqueueMessage(Landroid/os/Message;J)Z
+Landroid/os/Message;->markInUse()V
+Landroid/os/Binder;-><init>()V
+Landroid/os/Binder;-><init>(Ljava/lang/String;)V
+Landroid/os/UserHandle;->isSameApp(II)Z
+Landroid/app/WindowConfiguration;-><init>()V
+Landroid/app/WindowConfiguration;->unset()V
+Landroid/content/Intent;->getPackage()Ljava/lang/String;
+Lcom/android/internal/util/ArrayUtils;->unstableRemoveIf(Ljava/util/ArrayList;Ljava/util/function/Predicate;)I
+Landroid/util/TypedValue;->complexToDimensionPixelSize(ILandroid/util/DisplayMetrics;)I
+Landroid/net/Uri$HierarchicalUri;->getAuthority()Ljava/lang/String;
+Landroid/app/IApplicationThread$Stub;->asBinder()Landroid/os/IBinder;
+Landroid/os/UserHandle;->getIdentifier()I
+Landroid/util/MemoryIntArray;->enforceNotClosed()V
+Landroid/util/MemoryIntArray;->isClosed()Z
+Landroid/os/MessageQueue;->next()Landroid/os/Message;
+Landroid/app/ContextImpl;->getResources()Landroid/content/res/Resources;
+Landroid/net/Uri$Builder;->path(Landroid/net/Uri$PathPart;)Landroid/net/Uri$Builder;
+Landroid/util/Singleton;->get()Ljava/lang/Object;
+Lcom/android/internal/util/MessageUtils;->findMessageNames([Ljava/lang/Class;[Ljava/lang/String;)Landroid/util/SparseArray;
+Landroid/app/ActivityManager;->getService()Landroid/app/IActivityManager;
+Landroid/content/ContentProvider;->access$100(Landroid/content/ContentProvider;Ljava/lang/String;)Ljava/lang/String;
+Landroid/content/ContentProvider;->setCallingPackage(Ljava/lang/String;)Ljava/lang/String;
+Landroid/content/ContentProvider;->onCallingPackageChanged()V
+Landroid/app/ContextImpl;->getUserId()I
+Landroid/util/TimingsTraceLog;->assertSameThread()V
+Landroid/net/Uri$StringUri;->getAuthorityPart()Landroid/net/Uri$Part;
+Landroid/os/Binder;->attachInterface(Landroid/os/IInterface;Ljava/lang/String;)V
+Landroid/net/Uri$Builder;->authority(Landroid/net/Uri$Part;)Landroid/net/Uri$Builder;
+Landroid/app/NotificationChannel;->safeInt(Lorg/xmlpull/v1/XmlPullParser;Ljava/lang/String;I)I
+Landroid/app/NotificationChannel;->tryParseInt(Ljava/lang/String;I)I
+Landroid/app/NotificationChannel;->safeBool(Lorg/xmlpull/v1/XmlPullParser;Ljava/lang/String;Z)Z
+Landroid/net/Uri;-><init>(Landroid/net/Uri$1;)V
+Landroid/net/Uri;-><init>()V
+Landroid/net/Uri$AbstractHierarchicalUri;-><init>(Landroid/net/Uri$1;)V
+Landroid/net/Uri$AbstractHierarchicalUri;-><init>()V
+Landroid/app/NotificationChannel;->getTrimmedString(Ljava/lang/String;)Ljava/lang/String;
+Landroid/app/ActivityManager;->isLowRamDeviceStatic()Z
+Landroid/content/IntentFilter;->matchCategories(Ljava/util/Set;)Ljava/lang/String;
+Landroid/util/ArraySet;->ensureCapacity(I)V
+Landroid/util/ArraySet$1;-><init>(Landroid/util/ArraySet;)V
+Landroid/util/MapCollections$KeySet;-><init>(Landroid/util/MapCollections;)V
+Landroid/provider/Settings$GenerationTracker;->getCurrentGeneration()I
+Landroid/app/NotificationChannel;->getAudioAttributes()Landroid/media/AudioAttributes;
+Landroid/app/NotificationChannel;->getName()Ljava/lang/CharSequence;
+Landroid/app/NotificationChannel;->getImportance()I
+Landroid/app/NotificationChannel;->getOriginalImportance()I
+Lcom/android/internal/util/ArrayUtils;->size([Ljava/lang/Object;)I
+Landroid/app/NotificationChannel;->canShowBadge()Z
+Landroid/app/NotificationChannel;->getGroup()Ljava/lang/String;
+Lcom/android/internal/util/function/pooled/PooledLambdaImpl;->setIfInBounds([Ljava/lang/Object;ILjava/lang/Object;)V
+Lcom/android/internal/util/function/pooled/PooledLambdaImpl;->mask(II)I
+Landroid/os/Message;->obtain()Landroid/os/Message;
+Landroid/os/Handler;->enqueueMessage(Landroid/os/MessageQueue;Landroid/os/Message;J)Z
+Landroid/os/ThreadLocalWorkSource;->getUid()I
+Landroid/os/Handler;->sendMessageAtTime(Landroid/os/Message;J)Z
+Landroid/app/NotificationChannel;->isBlockableSystem()Z
+Landroid/app/NotificationChannel;->getId()Ljava/lang/String;
+Landroid/app/NotificationChannel;->getDescription()Ljava/lang/String;
+Landroid/app/NotificationChannel;->shouldVibrate()Z
+Landroid/app/NotificationChannel;->getUserLockedFields()I
+Landroid/app/NotificationChannel;->shouldShowLights()Z
+Landroid/app/NotificationChannel;->isDeleted()Z
+Landroid/app/NotificationChannel;->isFgServiceShown()Z
+Landroid/app/NotificationChannel;->writeXml(Lorg/xmlpull/v1/XmlSerializer;)V
+Landroid/app/NotificationChannel;->writeXml(Lorg/xmlpull/v1/XmlSerializer;ZLandroid/content/Context;)V
+Landroid/app/NotificationChannel;->canBypassDnd()Z
+Landroid/app/NotificationChannel;->getLockscreenVisibility()I
+Landroid/app/NotificationChannel;->getSound()Landroid/net/Uri;
+Landroid/media/AudioAttributes;->getUsage()I
+Landroid/media/AudioAttributes;->getContentType()I
+Landroid/media/AudioAttributes;->getFlags()I
+Landroid/app/NotificationChannel;->getLightColor()I
+Landroid/app/NotificationChannel;->getVibrationPattern()[J
+Landroid/app/NotificationChannel;->canBubble()Z
+Landroid/net/Uri$StringUri;->toString()Ljava/lang/String;
+Landroid/os/Handler;->sendMessageDelayed(Landroid/os/Message;J)Z
+Landroid/os/Message;->recycleUnchecked()V
+Landroid/net/Uri$PathPart;->getEncoded()Ljava/lang/String;
+Landroid/net/Uri$PathSegments;->get(I)Ljava/lang/Object;
+Landroid/net/Uri$PathSegments;->get(I)Ljava/lang/String;
+Landroid/net/Uri$PathSegmentsBuilder;->add(Ljava/lang/String;)V
+Landroid/content/ContentProvider;->getAuthorityWithoutUserId(Ljava/lang/String;)Ljava/lang/String;
+Landroid/os/UserHandle;->myUserId()I
+Landroid/provider/Settings$NameValueCache;->getStringForUser(Landroid/content/ContentResolver;Ljava/lang/String;I)Ljava/lang/String;
+Landroid/net/Uri$StringUri;->getAuthority()Ljava/lang/String;
+Landroid/os/BaseBundle;->getString(Ljava/lang/String;)Ljava/lang/String;
+Landroid/os/Bundle;->setDefusable(Landroid/os/Bundle;Z)Landroid/os/Bundle;
+Landroid/provider/Settings$ContentProviderHolder;->getProvider(Landroid/content/ContentResolver;)Landroid/content/IContentProvider;
+Landroid/content/ContentResolver;->getPackageName()Ljava/lang/String;
+Landroid/provider/Settings$ContentProviderHolder;->access$000(Landroid/provider/Settings$ContentProviderHolder;)Landroid/net/Uri;
+Landroid/content/ContentProvider$Transport;->call(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Landroid/os/Bundle;)Landroid/os/Bundle;
+Landroid/content/ContentProvider;->access$200(Landroid/content/ContentProvider;Ljava/lang/String;)V
+Landroid/content/ContentProvider;->validateIncomingAuthority(Ljava/lang/String;)V
+Landroid/content/ContentProvider;->matchesOurAuthorities(Ljava/lang/String;)Z
+Landroid/content/ContentProvider;->call(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Landroid/os/Bundle;)Landroid/os/Bundle;
+Landroid/provider/Settings;->isInSystemServer()Z
+Landroid/os/BaseBundle;-><init>(Ljava/lang/ClassLoader;I)V
+Landroid/os/BaseBundle;->putInt(Ljava/lang/String;I)V
+Landroid/os/Bundle;-><init>()V
+Landroid/os/BaseBundle;-><init>()V
+Landroid/os/BaseBundle;->getInt(Ljava/lang/String;I)I
+Landroid/os/Bundle;->setDefusable(Z)V
+Landroid/os/BaseBundle;->containsKey(Ljava/lang/String;)Z
+Landroid/app/ActivityManager;->handleIncomingUser(IIIZZLjava/lang/String;Ljava/lang/String;)I
+Landroid/provider/Settings$System;->getStringForUser(Landroid/content/ContentResolver;Ljava/lang/String;I)Ljava/lang/String;
+Landroid/provider/Settings$System;->getIntForUser(Landroid/content/ContentResolver;Ljava/lang/String;II)I
+Landroid/media/AudioSystem;->getOutputDeviceName(I)Ljava/lang/String;
+Landroid/app/ContextImpl;->getContentResolver()Landroid/content/ContentResolver;
+Landroid/content/IntentFilter;->matchData(Ljava/lang/String;Ljava/lang/String;Landroid/net/Uri;)I
+Landroid/content/Intent;->getFlags()I
+Landroid/util/Slog;->i(Ljava/lang/String;Ljava/lang/String;)I
+Lcom/android/server/LocalServices;->getService(Ljava/lang/Class;)Ljava/lang/Object;
+Lcom/android/internal/util/BitUtils;->unpackBits(J)[I
+Landroid/util/SparseIntArray;->get(II)I
+Landroid/os/BaseBundle;->copyInternal(Landroid/os/BaseBundle;Z)V
+Landroid/app/ActivityThread;->getPackageManager()Landroid/content/pm/IPackageManager;
+Landroid/app/AppGlobals;->getPackageManager()Landroid/content/pm/IPackageManager;
+Landroid/os/BaseBundle;-><init>(Z)V
+Lcom/android/internal/util/XmlUtils;->readThisArrayMapXml(Lorg/xmlpull/v1/XmlPullParser;Ljava/lang/String;[Ljava/lang/String;Lcom/android/internal/util/XmlUtils$ReadMapCallback;)Landroid/util/ArrayMap;
+Landroid/os/BaseBundle;->deepCopyValue(Ljava/lang/Object;)Ljava/lang/Object;
+Lcom/android/internal/util/XmlUtils;->readThisValueXml(Lorg/xmlpull/v1/XmlPullParser;[Ljava/lang/String;Lcom/android/internal/util/XmlUtils$ReadMapCallback;Z)Ljava/lang/Object;
+Landroid/os/PersistableBundle;-><init>(Landroid/util/ArrayMap;)V
+Lcom/android/internal/util/BitUtils;->packBits([I)J
+Landroid/os/PersistableBundle;->isValidType(Ljava/lang/Object;)Z
+Lcom/android/internal/util/XmlUtils;->readThisPrimitiveValueXml(Lorg/xmlpull/v1/XmlPullParser;Ljava/lang/String;)Ljava/lang/Object;
+Landroid/net/UidRange;->hashCode()I
+Landroid/util/Pair;-><init>(Ljava/lang/Object;Ljava/lang/Object;)V
+Landroid/os/LocaleList;->hashCode()I
+Landroid/content/IIntentReceiver$Stub;->asBinder()Landroid/os/IBinder;
+Landroid/app/job/JobInfo;->getRequiredNetwork()Landroid/net/NetworkRequest;
+Landroid/content/IntentFilter;->addAction(Ljava/lang/String;)V
+Lcom/android/internal/os/ProcTimeInStateReader;->initializeTimeInStateFormat(Ljava/nio/file/Path;)V
+Landroid/net/Uri$AbstractPart;-><init>(Ljava/lang/String;Ljava/lang/String;)V
+Landroid/os/MessageQueue;->removeMessages(Landroid/os/Handler;ILjava/lang/Object;)V
+Landroid/os/ServiceManager;->getIServiceManager()Landroid/os/IServiceManager;
+Landroid/util/Slog;->d(Ljava/lang/String;Ljava/lang/String;)I
+Lcom/android/internal/util/StatLogger;->getTime()J
+Landroid/util/TimingsTraceLog;->traceBegin(Ljava/lang/String;)V
+Landroid/util/TimingsTraceLog;->traceEnd()V
+Landroid/util/TimingsTraceLog;->logDuration(Ljava/lang/String;J)V
+Landroid/net/Uri$HierarchicalUri;-><init>(Ljava/lang/String;Landroid/net/Uri$Part;Landroid/net/Uri$PathPart;Landroid/net/Uri$Part;Landroid/net/Uri$Part;Landroid/net/Uri$1;)V
+Landroid/net/Uri$HierarchicalUri;-><init>(Ljava/lang/String;Landroid/net/Uri$Part;Landroid/net/Uri$PathPart;Landroid/net/Uri$Part;Landroid/net/Uri$Part;)V
+Landroid/net/Uri$Builder;-><init>()V
+Landroid/net/Uri$Builder;->scheme(Ljava/lang/String;)Landroid/net/Uri$Builder;
+Landroid/net/Uri$Builder;->query(Landroid/net/Uri$Part;)Landroid/net/Uri$Builder;
+Landroid/net/Uri$Builder;->fragment(Landroid/net/Uri$Part;)Landroid/net/Uri$Builder;
+Landroid/net/Uri$Builder;->build()Landroid/net/Uri;
+Landroid/net/Uri$Builder;->hasSchemeOrAuthority()Z
+Landroid/net/Uri$PathPart;->makeAbsolute(Landroid/net/Uri$PathPart;)Landroid/net/Uri$PathPart;
+Landroid/app/ContextImpl;->getSystemService(Ljava/lang/String;)Ljava/lang/Object;
+Landroid/app/SystemServiceRegistry;->getSystemService(Landroid/app/ContextImpl;Ljava/lang/String;)Ljava/lang/Object;
+Landroid/util/ArrayMap;->isEmpty()Z
+Landroid/app/SystemServiceRegistry$CachedServiceFetcher;->getService(Landroid/app/ContextImpl;)Ljava/lang/Object;
+Lcom/android/internal/util/StateMachine$SmHandler;->completeConstruction()V
+Landroid/os/SystemProperties;->getInt(Ljava/lang/String;I)I
+Landroid/os/ThreadLocalWorkSource;->setUid(I)J
+Landroid/os/ThreadLocalWorkSource;->getToken()J
+Landroid/os/ThreadLocalWorkSource;->restore(J)V
+Landroid/os/ThreadLocalWorkSource;->parseUidFromToken(J)I
+Lcom/android/internal/util/function/pooled/PooledLambdaImpl;->fillInArg(Ljava/lang/Object;)Z
+Lcom/android/internal/util/function/pooled/PooledLambdaImpl;->access$000(II)I
+Landroid/os/Handler;->dispatchMessage(Landroid/os/Message;)V
+Lcom/android/internal/util/function/pooled/PooledLambdaImpl;->invoke(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
+Lcom/android/internal/util/ArrayUtils;->contains([II)Z
+Landroid/os/Handler;-><init>(Landroid/os/Looper;Landroid/os/Handler$Callback;Z)V
+Landroid/os/UserHandle;->isIsolated(I)Z
+Landroid/app/ContextImpl;->checkPermission(Ljava/lang/String;II)I
+Landroid/app/ContextImpl;->checkCallingOrSelfPermission(Ljava/lang/String;)I
+Landroid/net/Uri$StringUri;->findSchemeSeparator()I
+Landroid/content/pm/PackageUserState;->isMatch(Landroid/content/pm/ComponentInfo;I)Z
+Landroid/content/pm/PackageUserState;->isEnabled(Landroid/content/pm/ComponentInfo;I)Z
+Landroid/content/pm/PackageUserState;->reportIfDebug(ZI)Z
+Landroid/content/pm/PackageParser$Package;->isExternal()Z
+Landroid/content/pm/ApplicationInfo;->isExternal()Z
+Landroid/content/pm/ApplicationInfo;->isSystemExt()Z
+Landroid/util/Spline$MonotoneCubicSpline;->interpolate(F)F
+Landroid/app/job/JobInfo;->getId()I
+Landroid/util/Spline$MonotoneCubicSpline;-><init>([F[F)V
+Landroid/content/res/ApkAssets;->getStringFromPool(I)Ljava/lang/CharSequence;
+Landroid/util/MemoryIntArray;->size()I
+Landroid/os/Process;->myTid()I
+Landroid/app/-$$Lambda$ResourcesManager$QJ7UiVk_XS90KuXAsIjIEym1DnM;->test(Ljava/lang/Object;)Z
+Landroid/app/ResourcesManager;->lambda$static$0(Ljava/lang/ref/WeakReference;)Z
+Landroid/app/ResourcesManager;->getOrCreateResourcesLocked(Ljava/lang/ClassLoader;Landroid/content/res/ResourcesImpl;Landroid/content/res/CompatibilityInfo;)Landroid/content/res/Resources;
+Landroid/graphics/Rect;->isEmpty()Z
+Landroid/content/res/ResourcesImpl;->flushLayoutCache()V
+Landroid/os/LocaleList;->get(I)Ljava/util/Locale;
+Landroid/content/res/ThemedResourceCache;->onConfigurationChange(I)V
+Landroid/content/res/ThemedResourceCache;->prune(I)Z
+Landroid/content/res/Configuration;->compareTo(Landroid/content/res/Configuration;)I
+Landroid/content/res/Resources;->getClassLoader()Ljava/lang/ClassLoader;
+Lcom/android/internal/os/CachedDeviceState;->access$200(Lcom/android/internal/os/CachedDeviceState;)Z
+Landroid/graphics/Rect;->equals(Ljava/lang/Object;)Z
+Landroid/content/res/Configuration;->equals(Landroid/content/res/Configuration;)Z
+Lcom/android/internal/os/CachedDeviceState$Readonly;->isCharging()Z
+Landroid/util/MemoryIntArray;->enforceValidIndex(I)V
+Landroid/util/MemoryIntArray;->get(I)I
+Lcom/android/internal/os/LooperStats;->deviceStateAllowsCollection()Z
+Landroid/content/res/AssetManager;->isUpToDate()Z
+Landroid/content/res/ApkAssets;->isUpToDate()Z
+Landroid/content/res/Resources;->getImpl()Landroid/content/res/ResourcesImpl;
+Landroid/util/SparseBooleanArray;->put(IZ)V
+Lcom/android/internal/util/GrowingArrayUtils;->insert([ZIIZ)[Z
+Landroid/os/Parcel;->readLongArray([J)V
+Landroid/os/Handler;->sendMessage(Landroid/os/Message;)Z
+Landroid/app/ActivityThread;->getApplicationThread()Landroid/app/ActivityThread$ApplicationThread;
+Landroid/content/res/TypedArray;->getBoolean(IZ)Z
+Landroid/content/res/TypedArray;->getInt(II)I
+Landroid/content/res/TypedArray;->getResourceId(II)I
+Landroid/content/res/TypedArray;->getString(I)Ljava/lang/String;
+Landroid/content/res/TypedArray;->loadStringValueAt(I)Ljava/lang/CharSequence;
+Landroid/content/res/XmlBlock$Parser;->getPooledString(I)Ljava/lang/CharSequence;
+Landroid/view/inputmethod/InputMethodInfo;-><init>(Landroid/content/Context;Landroid/content/pm/ResolveInfo;Ljava/util/List;)V
+Landroid/view/inputmethod/InputMethodInfo;->getSubtypeAt(I)Landroid/view/inputmethod/InputMethodSubtype;
+Landroid/view/inputmethod/InputMethodSubtypeArray;->get(I)Landroid/view/inputmethod/InputMethodSubtype;
+Landroid/view/inputmethod/InputMethodSubtype;->hashCode()I
+Landroid/provider/Settings$GenerationTracker;->readCurrentGeneration()I
+Landroid/text/TextUtils$SimpleStringSplitter;->next()Ljava/lang/String;
+Landroid/view/inputmethod/InputMethodSubtype;->sort(Landroid/content/Context;ILandroid/view/inputmethod/InputMethodInfo;Ljava/util/List;)Ljava/util/List;
+Landroid/content/res/Configuration;->updateFrom(Landroid/content/res/Configuration;)I
+Landroid/app/WindowConfiguration;->updateFrom(Landroid/app/WindowConfiguration;)I
+Landroid/app/AppOpsManager;->permissionToOpCode(Ljava/lang/String;)I
+Landroid/util/SparseIntArray;->put(II)V
+Landroid/app/AppOpsManager;->opToSwitch(I)I
+Landroid/app/ApplicationPackageManager;->updateFlagsForPackage(II)I
+Landroid/app/ContextImpl;->getOpPackageName()Ljava/lang/String;
+Landroid/content/pm/PermissionInfo;->isHardRestricted()Z
+Landroid/app/ContextImpl;->getPackageManager()Landroid/content/pm/PackageManager;
+Landroid/content/pm/PermissionInfo;->isSoftRestricted()Z
+Landroid/app/ApplicationPackageManager;->getUserId()I
+Landroid/app/ApplicationPackageManager;->getPermissionInfo(Ljava/lang/String;I)Landroid/content/pm/PermissionInfo;
+Landroid/content/pm/PackageParser;->generatePermissionInfo(Landroid/content/pm/PackageParser$Permission;I)Landroid/content/pm/PermissionInfo;
+Landroid/content/pm/PermissionInfo;->isRestricted()Z
+Landroid/app/ApplicationPackageManager;->getPermissionFlags(Ljava/lang/String;Ljava/lang/String;Landroid/os/UserHandle;)I
+Landroid/os/Process;->myPid()I
+Lcom/android/internal/util/IntPair;->of(II)J
+Landroid/util/SparseIntArray;->indexOfKey(I)I
+Landroid/util/SparseBooleanArray;->get(IZ)Z
+Landroid/util/SparseBooleanArray;->get(I)Z
+Landroid/app/ApplicationPackageManager;->getPackageInfoAsUser(Ljava/lang/String;II)Landroid/content/pm/PackageInfo;
+Landroid/os/Binder;->getInterfaceDescriptor()Ljava/lang/String;
+Landroid/os/Binder;->queryLocalInterface(Ljava/lang/String;)Landroid/os/IInterface;
+Landroid/content/ContentResolver;->getUserId()I
+Landroid/net/NetworkStatsHistory$DataStreamUtils;->readVarLong(Ljava/io/DataInputStream;)J
+Landroid/content/pm/PackageItemInfo;-><init>(Landroid/content/pm/PackageItemInfo;)V
+Landroid/system/suspend/WakeLockInfo$1;->createFromParcel(Landroid/os/Parcel;)Ljava/lang/Object;
+Landroid/system/suspend/WakeLockInfo$1;->createFromParcel(Landroid/os/Parcel;)Landroid/system/suspend/WakeLockInfo;
+Landroid/system/suspend/WakeLockInfo;-><init>()V
+Landroid/system/suspend/WakeLockInfo;->readFromParcel(Landroid/os/Parcel;)V
+Lcom/android/internal/os/KernelWakelockReader;->updateWakelockStats([Landroid/system/suspend/WakeLockInfo;Lcom/android/internal/os/KernelWakelockStats;)Lcom/android/internal/os/KernelWakelockStats;
+Landroid/net/NetworkStatsHistory$DataStreamUtils;->readVarLongArray(Ljava/io/DataInputStream;)[J
+Landroid/net/NetworkStatsHistory;->setLong([JIJ)V
+Landroid/net/NetworkStatsHistory;->addLong([JIJ)V
+Landroid/net/NetworkStatsHistory;->getLong([JIJ)J
+Lcom/android/internal/util/ProcFileReader;->finishLine()V
+Landroid/content/res/Resources;->getText(I)Ljava/lang/CharSequence;
+Landroid/content/res/AssetManager;->getResourceText(I)Ljava/lang/CharSequence;
+Landroid/util/TypedValue;->coerceToString()Ljava/lang/CharSequence;
+Landroid/util/SparseIntArray;->valueAt(I)I
+Landroid/content/res/Resources;->getString(I)Ljava/lang/String;
+Lcom/android/internal/os/LooperStats;->messageDispatchStarting()Ljava/lang/Object;
+Lcom/android/internal/os/LooperStats;->messageDispatched(Ljava/lang/Object;Landroid/os/Message;)V
+Landroid/os/storage/StorageManager;->convert(Ljava/util/UUID;)Ljava/lang/String;
+Landroid/os/Parcel;->readSparseArray(Ljava/lang/ClassLoader;)Landroid/util/SparseArray;
+Landroid/util/SparseIntArray;->get(I)I
+Landroid/content/pm/ApplicationInfo;-><init>(Landroid/content/pm/ApplicationInfo;)V
+Landroid/os/UserHandle;->isApp(I)Z
+Landroid/util/SparseIntArray;->delete(I)V
+Landroid/util/SparseIntArray;->size()I
+Landroid/util/SparseIntArray;->keyAt(I)I
+Lcom/android/internal/util/ArrayUtils;->convertToIntArray(Ljava/util/List;)[I
+Landroid/os/Parcel;->writeIntArray([I)V
+Landroid/os/Parcel;->obtain(J)Landroid/os/Parcel;
+Landroid/app/ContextImpl;->getOuterContext()Landroid/content/Context;
+Landroid/content/pm/PackageParser;->generateProviderInfo(Landroid/content/pm/PackageParser$Provider;ILandroid/content/pm/PackageUserState;I)Landroid/content/pm/ProviderInfo;
+Landroid/view/DisplayAdjustments;->getCompatibilityInfo()Landroid/content/res/CompatibilityInfo;
+Landroid/net/Uri$StringUri;->getScheme()Ljava/lang/String;
+Landroid/net/Uri$StringUri;->getPathPart()Landroid/net/Uri$PathPart;
+Landroid/app/WindowConfiguration;->compareTo(Landroid/app/WindowConfiguration;)I
+Landroid/content/res/Configuration;->hashCode()I
+Landroid/content/res/Configuration;->setToDefaults()V
+Landroid/os/LocaleList;->getEmptyLocaleList()Landroid/os/LocaleList;
+Landroid/content/res/Configuration;-><init>(Landroid/content/res/Configuration;)V
+Landroid/os/Parcel;->readStrongBinder()Landroid/os/IBinder;
+Landroid/util/Pair;->create(Ljava/lang/Object;Ljava/lang/Object;)Landroid/util/Pair;
+Landroid/os/UserHandle;->isCore(I)Z
+Landroid/app/ContextImpl;->enforce(Ljava/lang/String;IZILjava/lang/String;)V
+Landroid/app/ContextImpl;->enforceCallingOrSelfPermission(Ljava/lang/String;Ljava/lang/String;)V
+Landroid/content/res/CompatibilityInfo;->supportsScreen()Z
+Landroid/content/res/CompatibilityInfo;->isScalingRequired()Z
+Landroid/app/job/JobInfo;->getFlags()I
+Landroid/content/SyncAdapterType;->equals(Ljava/lang/Object;)Z
+Landroid/content/pm/RegisteredServicesCache;->containsType(Ljava/util/ArrayList;Ljava/lang/Object;)Z
+Landroid/os/Looper;->showSlowLog(JJJLjava/lang/String;Landroid/os/Message;)Z
+Lcom/android/internal/util/function/pooled/PooledLambdaImpl;->setFlags(II)V
+Landroid/os/Parcel;->init(J)V
+Landroid/content/res/Resources;->getInteger(I)I
+Landroid/net/Uri$StringUri;->isHierarchical()Z
+Landroid/net/Uri$StringUri;->getQueryPart()Landroid/net/Uri$Part;
+Landroid/net/Uri$PathPart;->from(Ljava/lang/String;Ljava/lang/String;)Landroid/net/Uri$PathPart;
+Landroid/net/Uri$PathPart;-><init>(Ljava/lang/String;Ljava/lang/String;)V
+Landroid/net/Uri$PathPart;->fromEncoded(Ljava/lang/String;)Landroid/net/Uri$PathPart;
+Landroid/content/IntentFilter;-><init>(Landroid/content/IntentFilter;)V
+Landroid/util/proto/EncodedBuffer;->writeRawByte(B)V
+Landroid/content/Intent;->getComponent()Landroid/content/ComponentName;
+Landroid/util/proto/EncodedBuffer;->writeRawVarint32(I)V
+Landroid/util/proto/EncodedBuffer;->writeRawFixed32(I)V
+Landroid/util/proto/ProtoOutputStream;->assertNotCompacted()V
+Landroid/util/proto/ProtoOutputStream;->writeTag(II)V
+Landroid/util/proto/ProtoOutputStream;->write(JLjava/lang/String;)V
+Landroid/util/proto/ProtoOutputStream;->writeStringImpl(ILjava/lang/String;)V
+Landroid/os/Parcel;->dataSize()I
+Landroid/util/proto/EncodedBuffer;->writeRawBuffer([BII)V
+Landroid/util/proto/ProtoOutputStream;->writeUtf8String(ILjava/lang/String;)V
+Landroid/util/proto/ProtoOutputStream;->writeKnownLengthHeader(II)V
+Landroid/util/proto/EncodedBuffer;->writeRawBuffer([B)V
+Landroid/util/proto/ProtoStream;->getRepeatedFromToken(J)Z
+Landroid/util/proto/EncodedBuffer;->getWritePos()I
+Landroid/util/proto/EncodedBuffer;->getRawFixed32At(I)I
+Landroid/util/proto/EncodedBuffer;->editRawFixed32(II)V
+Landroid/util/proto/EncodedBuffer;->writeRawVarint64(J)V
+Landroid/os/StrictMode;->onBinderStrictModePolicyChange(I)V
+Landroid/util/proto/EncodedBuffer;->getRawVarint32Size(I)I
+Landroid/util/proto/EncodedBuffer;->readRawByte()B
+Landroid/util/proto/EncodedBuffer;->getReadPos()I
+Landroid/util/proto/ProtoOutputStream;->editEncodedSize(I)I
+Landroid/util/proto/EncodedBuffer;->readRawFixed32()I
+Landroid/util/proto/EncodedBuffer;->getReadableSize()I
+Landroid/util/proto/ProtoOutputStream;->readRawTag()I
+Landroid/util/proto/EncodedBuffer;->readRawUnsigned()J
+Landroid/os/MessageQueue;->removeMessages(Landroid/os/Handler;Ljava/lang/Runnable;Ljava/lang/Object;)V
+Landroid/net/Uri$PathSegmentsBuilder;->build()Landroid/net/Uri$PathSegments;
+Landroid/net/Uri$PathSegments;-><init>([Ljava/lang/String;I)V
+Landroid/util/proto/EncodedBuffer;->skipRead(I)V
+Landroid/app/IApplicationThread$Stub$Proxy;->asBinder()Landroid/os/IBinder;
+Landroid/app/ApplicationPackageManager;->getPackageInfo(Ljava/lang/String;I)Landroid/content/pm/PackageInfo;
+Landroid/util/proto/ProtoOutputStream;->compactSizes(I)V
+Landroid/util/proto/EncodedBuffer;->writeFromThisBuffer(II)V
+Landroid/app/WindowConfiguration;->getWindowingMode()I
+Lcom/android/internal/util/function/pooled/PooledLambdaImpl;->unmask(II)I
+Landroid/app/ContextImpl;->registerReceiverInternal(Landroid/content/BroadcastReceiver;ILandroid/content/IntentFilter;Ljava/lang/String;Landroid/os/Handler;Landroid/content/Context;I)Landroid/content/Intent;
+Landroid/app/ActivityThread;->getInstrumentation()Landroid/app/Instrumentation;
+Landroid/app/LoadedApk;->getReceiverDispatcher(Landroid/content/BroadcastReceiver;Landroid/content/Context;Landroid/os/Handler;Landroid/app/Instrumentation;Z)Landroid/content/IIntentReceiver;
+Landroid/app/LoadedApk$ReceiverDispatcher;->getIIntentReceiver()Landroid/content/IIntentReceiver;
+Landroid/util/SparseArray;->gc()V
+Landroid/net/Uri$StringUri;->buildUpon()Landroid/net/Uri$Builder;
+Landroid/net/Uri$StringUri;->getFragmentPart()Landroid/net/Uri$Part;
+Landroid/net/Uri$PathPart;->appendEncodedSegment(Landroid/net/Uri$PathPart;Ljava/lang/String;)Landroid/net/Uri$PathPart;
+Landroid/content/ContentResolver;->getContentService()Landroid/content/IContentService;
+Lcom/android/internal/os/BinderDeathDispatcher;->linkToDeath(Landroid/os/IInterface;Landroid/os/IBinder$DeathRecipient;)I
+Landroid/net/NetworkCapabilities;->appendStringRepresentationOfBitMaskToStringBuilder(Ljava/lang/StringBuilder;JLandroid/net/NetworkCapabilities$NameOf;Ljava/lang/String;)V
+Landroid/os/Parcel;->writeStringArray([Ljava/lang/String;)V
+Lcom/android/internal/util/StatLogger;->logDurationStat(IJ)J
+Lcom/android/internal/util/CollectionUtils;->size(Ljava/util/Collection;)I
+Landroid/content/ComponentName;->getPackageName()Ljava/lang/String;
+Landroid/os/MessageQueue;->removeCallbacksAndMessages(Landroid/os/Handler;Ljava/lang/Object;)V
+Lcom/android/internal/util/GrowingArrayUtils;->append([III)[I
+Landroid/content/pm/ApplicationInfo;->isDirectBootAware()Z
+Landroid/content/res/Configuration;->unset()V
+Landroid/util/FastImmutableArraySet$FastIterator;->hasNext()Z
+Landroid/util/FastImmutableArraySet;->iterator()Ljava/util/Iterator;
+Landroid/util/FastImmutableArraySet$FastIterator;->next()Ljava/lang/Object;
+Landroid/app/WindowConfiguration;->getActivityType()I
+Landroid/app/WindowConfiguration;->getBounds()Landroid/graphics/Rect;
+Landroid/content/res/Configuration;-><init>()V
+Landroid/util/proto/ProtoOutputStream;->write(JI)V
+Landroid/util/proto/ProtoOutputStream;->writeInt32Impl(II)V
+Landroid/os/Parcel;->writeStrongBinder(Landroid/os/IBinder;)V
+Landroid/os/Parcel;->writeValue(Ljava/lang/Object;)V
+Lcom/android/internal/util/function/pooled/PooledLambdaImpl;->popArg(I)Ljava/lang/Object;
+Lcom/android/internal/util/function/pooled/PooledLambdaImpl;->isInvocationArgAtIndex(I)Z
+Landroid/util/ArrayMap;->putAll(Landroid/util/ArrayMap;)V
+Landroid/os/Looper;->myLooper()Landroid/os/Looper;
+Landroid/net/NetworkScoreManager;->getActiveScorerPackage()Ljava/lang/String;
+Landroid/appwidget/AppWidgetManager;->isBoundWidgetPackage(Ljava/lang/String;I)Z
+Landroid/os/SystemProperties;->get(Ljava/lang/String;)Ljava/lang/String;
+Landroid/content/res/Configuration;->getLocales()Landroid/os/LocaleList;
+Landroid/content/res/ConfigurationBoundResourceCache;->onConfigurationChange(I)V
+Landroid/content/Intent;->getCategories()Ljava/util/Set;
+Landroid/os/LocaleList;->equals(Ljava/lang/Object;)Z
+Landroid/content/res/CompatibilityInfo;->hashCode()I
+Landroid/os/Message;->sendToTarget()V
+Landroid/os/Handler;->getPostMessage(Ljava/lang/Runnable;)Landroid/os/Message;
+Landroid/app/ApplicationPackageManager;->getPackagesForUid(I)[Ljava/lang/String;
+Lcom/android/internal/util/function/pooled/PooledLambdaImpl$LambdaType;->encode(II)I
+Landroid/os/BinderProxy$ProxyMap;->hash(J)I
+Lcom/android/internal/util/function/pooled/PooledLambdaImpl;->getFlags(I)I
+Lcom/android/internal/util/function/pooled/PooledLambdaImpl$LambdaType;->decodeArgCount(I)I
+Lcom/android/internal/util/function/pooled/PooledLambdaImpl;->isRecycled()Z
+Landroid/os/Handler;->post(Ljava/lang/Runnable;)Z
+Landroid/os/SystemClock$2;->millis()J
+Landroid/os/Binder;->execTransact(IJJI)Z
+Landroid/os/Binder;->execTransactInternal(IJJII)Z
+Landroid/os/Parcel;->enforceInterface(Ljava/lang/String;)V
+Landroid/database/IContentObserver$Stub;->asBinder()Landroid/os/IBinder;
+Landroid/os/StrictMode;->clearGatheredViolations()V
+Landroid/os/Binder;->linkToDeath(Landroid/os/IBinder$DeathRecipient;I)V
+Landroid/os/Parcel;->writeNoException()V
+Landroid/os/StrictMode;->hasGatheredViolations()Z
+Landroid/os/Handler;->obtainMessage(IIILjava/lang/Object;)Landroid/os/Message;
+Landroid/os/Message;->obtain(Landroid/os/Handler;IIILjava/lang/Object;)Landroid/os/Message;
+Landroid/os/StrictMode$AndroidBlockGuardPolicy;->setThreadPolicyMask(I)V
+Landroid/os/Looper;->loop()V
+Landroid/app/usage/UsageEvents$Event;->getClassName()Ljava/lang/String;
+Landroid/app/usage/UsageStats;->update(Ljava/lang/String;JII)V
+Lcom/android/internal/os/BinderCallsStats;->callStarted(Landroid/os/Binder;II)Lcom/android/internal/os/BinderInternal$CallSession;
+Landroid/os/Parcel;->readCallingWorkSourceUid()I
+Lcom/android/internal/os/BinderCallsStats;->callEnded(Lcom/android/internal/os/BinderInternal$CallSession;III)V
+Landroid/os/Parcel;->writeParcelable(Landroid/os/Parcelable;I)V
+Landroid/os/Parcel;->writeFloat(F)V
+Landroid/view/DisplayCutout;->getSafeInsetTop()I
+Landroid/content/res/Resources;->getDimensionPixelSize(I)I
+Landroid/os/Parcel;->writeParcelableCreator(Landroid/os/Parcelable;)V
+Landroid/content/Intent;->getScheme()Ljava/lang/String;
+Landroid/os/Handler;-><init>(Landroid/os/Looper;)V
+Landroid/os/BaseBundle;->putString(Ljava/lang/String;Ljava/lang/String;)V
+Landroid/content/SyncAdaptersCache;->getSyncAdapterPackagesForAuthority(Ljava/lang/String;I)[Ljava/lang/String;
+Landroid/view/Display;->hasAccess(IIII)Z
+Landroid/view/DisplayInfo;->writeToParcel(Landroid/os/Parcel;I)V
+Landroid/view/DisplayInfo;->hasAccess(I)Z
+Landroid/os/BinderProxy$ProxyMap;->get(J)Landroid/os/BinderProxy;
+Landroid/os/Parcel;->writeArrayMapInternal(Landroid/util/ArrayMap;)V
+Landroid/content/Intent;->getData()Landroid/net/Uri;
+Landroid/util/ArraySet;->addAll(Landroid/util/ArraySet;)V
+Landroid/os/Binder$PropagateWorkSourceTransactListener;->onTransactStarted(Landroid/os/IBinder;I)Ljava/lang/Object;
+Landroid/os/Binder$PropagateWorkSourceTransactListener;->onTransactEnded(Ljava/lang/Object;)V
+Landroid/os/RemoteCallbackList;->beginBroadcast()I
+Landroid/os/BinderProxy;->getInstance(JJ)Landroid/os/BinderProxy;
+Landroid/content/Intent;->setAction(Ljava/lang/String;)Landroid/content/Intent;
+Landroid/view/Display$HdrCapabilities;->writeToParcel(Landroid/os/Parcel;I)V
+Landroid/graphics/Rect;->set(IIII)V
+Landroid/content/res/Configuration;->equals(Ljava/lang/Object;)Z
+Landroid/os/Message;->obtain(Landroid/os/Handler;ILjava/lang/Object;)Landroid/os/Message;
+Landroid/util/proto/ProtoOutputStream;->start(J)J
+Landroid/util/proto/ProtoOutputStream;->startObjectImpl(IZ)J
+Landroid/util/proto/ProtoOutputStream;->getTagSize(I)I
+Landroid/util/proto/ProtoOutputStream;->end(J)V
+Landroid/util/proto/ProtoOutputStream;->endObjectImpl(JZ)V
+Landroid/util/proto/ProtoStream;->getDepthFromToken(J)I
+Landroid/util/proto/ProtoOutputStream;->writeUnsignedVarintFromSignedInt(I)V
+Landroid/os/Handler;->obtainMessage(ILjava/lang/Object;)Landroid/os/Message;
+Landroid/graphics/Rect;->width()I
+Landroid/app/ApplicationPackageManager;->updateFlagsForApplication(II)I
+Lcom/android/internal/os/ZygoteArguments;->parseArgs([Ljava/lang/String;)V
+Landroid/os/RemoteCallbackList;->finishBroadcast()V
+Landroid/os/BinderProxy;->queryLocalInterface(Ljava/lang/String;)Landroid/os/IInterface;
+Landroid/content/Intent;-><init>(Landroid/content/Intent;I)V
+Landroid/content/Intent;->addFlags(I)Landroid/content/Intent;
+Landroid/content/ContentResolver;->registerContentObserver(Landroid/net/Uri;ZLandroid/database/ContentObserver;I)V
+Landroid/database/ContentObserver;->getContentObserver()Landroid/database/IContentObserver;
+Landroid/net/Uri$StringUri;->parsePath(Ljava/lang/String;I)Ljava/lang/String;
+Landroid/content/Intent;-><init>(Ljava/lang/String;)V
+Landroid/graphics/Rect;->height()I
+Landroid/provider/Settings$Global;->getStringForUser(Landroid/content/ContentResolver;Ljava/lang/String;I)Ljava/lang/String;
+Landroid/util/LongSparseArray;->valueAt(I)Ljava/lang/Object;
+Landroid/os/Handler;->removeMessages(I)V
+Landroid/net/Uri$Part;->from(Ljava/lang/String;Ljava/lang/String;)Landroid/net/Uri$Part;
+Landroid/os/Parcel;->writeBundle(Landroid/os/Bundle;)V
+Landroid/os/BaseBundle;->getBoolean(Ljava/lang/String;Z)Z
+Landroid/os/BinderProxy$ProxyMap;->set(JLandroid/os/BinderProxy;)V
+Landroid/provider/Settings$Global;->getString(Landroid/content/ContentResolver;Ljava/lang/String;)Ljava/lang/String;
+Landroid/util/ArraySet;->isEmpty()Z
+Landroid/app/ActivityManager;->checkComponentPermission(Ljava/lang/String;IIZ)I
+Landroid/database/IContentObserver$Stub$Proxy;->asBinder()Landroid/os/IBinder;
+Landroid/os/Parcel;->writeTypedArray([Landroid/os/Parcelable;I)V
+Landroid/os/BinderProxy;-><init>(J)V
+Landroid/content/IIntentReceiver$Stub$Proxy;->asBinder()Landroid/os/IBinder;
+Landroid/os/Parcel;->writeTypedList(Ljava/util/List;I)V
+Landroid/app/ApplicationPackageManager;->getApplicationInfoAsUser(Ljava/lang/String;II)Landroid/content/pm/ApplicationInfo;
+Landroid/app/ApplicationPackageManager;->maybeAdjustApplicationInfo(Landroid/content/pm/ApplicationInfo;)Landroid/content/pm/ApplicationInfo;
+Landroid/app/ContextImpl;->getUser()Landroid/os/UserHandle;
+Landroid/content/pm/PackageManager;->getApplicationInfoAsUser(Ljava/lang/String;ILandroid/os/UserHandle;)Landroid/content/pm/ApplicationInfo;
+Landroid/app/AppOpsManager;->strOpToOp(Ljava/lang/String;)I
+Landroid/app/AppOpsManager;->opToPublicName(I)Ljava/lang/String;
+Landroid/app/AppOpsManager;->unsafeCheckOpRaw(Ljava/lang/String;ILjava/lang/String;)I
+Landroid/database/sqlite/SQLiteClosable;->releaseReference()V
+Lcom/android/internal/util/function/pooled/PooledLambdaImpl;->acquire(Lcom/android/internal/util/function/pooled/PooledLambdaImpl$Pool;Ljava/lang/Object;IIILjava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Lcom/android/internal/util/function/pooled/PooledLambda;
+Lcom/android/internal/util/function/pooled/PooledLambdaImpl;->acquire(Lcom/android/internal/util/function/pooled/PooledLambdaImpl$Pool;)Lcom/android/internal/util/function/pooled/PooledLambdaImpl;
+Lcom/android/internal/util/function/pooled/PooledLambdaImpl;->recycleOnUse()Lcom/android/internal/util/function/pooled/PooledRunnable;
+Lcom/android/internal/util/function/pooled/PooledLambdaImpl;->recycleOnUse()Lcom/android/internal/util/function/pooled/OmniFunction;
+Landroid/os/Message;->setCallback(Ljava/lang/Runnable;)Landroid/os/Message;
+Landroid/util/LongSparseLongArray;->indexOfKey(J)I
+Lcom/android/internal/util/function/pooled/OmniFunction;->run()V
+Lcom/android/internal/util/function/pooled/PooledLambdaImpl;->doInvoke()Ljava/lang/Object;
+Lcom/android/internal/util/function/pooled/PooledLambdaImpl$LambdaType;->decodeReturnType(I)I
+Lcom/android/internal/util/function/pooled/PooledLambdaImpl;->access$100(II)I
Lcom/android/internal/util/function/pooled/PooledLambdaImpl;->doRecycle()V
-Landroid/os/Handler;->postAtFrontOfQueue(Ljava/lang/Runnable;)Z
+Landroid/util/Pair;->hashCode()I
+Landroid/content/pm/ApplicationInfo;->hasRequestedLegacyExternalStorage()Z
+Landroid/util/ArrayMap;->remove(Ljava/lang/Object;)Ljava/lang/Object;
+Landroid/util/ArraySet;->clear()V
+Landroid/app/IActivityManager$Stub;->onTransact(ILandroid/os/Parcel;Landroid/os/Parcel;I)Z
+Landroid/text/TextUtils;->writeToParcel(Ljava/lang/CharSequence;Landroid/os/Parcel;I)V
+Landroid/os/Parcel;->writeMapInternal(Ljava/util/Map;)V
+Landroid/os/RemoteCallbackList;->getBroadcastItem(I)Landroid/os/IInterface;
+Landroid/app/WindowConfiguration;->canReceiveKeys()Z
+Landroid/graphics/Point;->offset(II)V
+Landroid/content/Intent;-><init>(Landroid/content/Intent;)V
+Landroid/os/Binder;->allowBlocking(Landroid/os/IBinder;)Landroid/os/IBinder;
+Landroid/os/Bundle;->hasFileDescriptors()Z
+Lcom/android/internal/app/procstats/ProcessStats;->updateTrackingAssociationsLocked(IJ)V
+Lcom/android/internal/app/procstats/SparseMappingTable$Table;->assertConsistency()V
+Lcom/android/internal/app/procstats/SparseMappingTable;->access$100(Lcom/android/internal/app/procstats/SparseMappingTable;)Ljava/util/ArrayList;
+Landroid/os/RemoteCallbackList;->getBroadcastCookie(I)Ljava/lang/Object;
+Landroid/net/Uri$StringUri;->parseAuthority(Ljava/lang/String;I)Ljava/lang/String;
+Landroid/os/ServiceManager;->getService(Ljava/lang/String;)Landroid/os/IBinder;
+Landroid/os/ServiceManager;->rawGetService(Ljava/lang/String;)Landroid/os/IBinder;
+Landroid/os/ServiceManagerProxy;->getService(Ljava/lang/String;)Landroid/os/IBinder;
+Landroid/os/IServiceManager$Stub$Proxy;->checkService(Ljava/lang/String;)Landroid/os/IBinder;
+Landroid/content/pm/PackageItemInfo;->writeToParcel(Landroid/os/Parcel;I)V
+Landroid/net/Uri$Part$EmptyPart;->isEmpty()Z
+Landroid/os/BaseBundle;-><init>(Landroid/os/BaseBundle;)V
+Landroid/os/Bundle;-><init>(Landroid/os/Bundle;)V
+Landroid/net/Uri$Part;->readFrom(Landroid/os/Parcel;)Landroid/net/Uri$Part;
+Landroid/content/ComponentName;->equals(Ljava/lang/Object;)Z
+Landroid/util/ArraySet;-><init>(Landroid/util/ArraySet;)V
+Landroid/os/Parcel;->createStringArray()[Ljava/lang/String;
+Landroid/os/Message;->setAsynchronous(Z)V
+Landroid/os/Parcel;->writeTypedList(Ljava/util/List;)V
+Landroid/os/Message;->obtain(Landroid/os/Handler;I)Landroid/os/Message;
+Lcom/android/internal/os/BatteryStatsImpl$StopwatchTimer;->refreshTimersLocked(JLjava/util/ArrayList;Lcom/android/internal/os/BatteryStatsImpl$StopwatchTimer;)J
+Landroid/os/Handler;->obtainMessage(I)Landroid/os/Message;
+Landroid/os/storage/StorageManager;->isUserKeyUnlocked(I)Z
+Landroid/hardware/display/IDisplayManager$Stub;->onTransact(ILandroid/os/Parcel;Landroid/os/Parcel;I)Z
+Landroid/os/Bundle;->writeToParcel(Landroid/os/Parcel;I)V
+Landroid/os/Parcel;->pushAllowFds(Z)Z
+Landroid/os/BaseBundle;->writeToParcelInner(Landroid/os/Parcel;I)V
+Landroid/os/Parcel;->restoreAllowFds(Z)V
+Landroid/content/pm/ApplicationInfo;->isEncryptionAware()Z
+Lcom/android/internal/app/procstats/ProcessState;->setCombinedState(IJ)V
+Landroid/os/Message;->obtain(Landroid/os/Handler;III)Landroid/os/Message;
+Landroid/hardware/display/DisplayManagerInternal$DisplayPowerRequest;->isBrightOrDim()Z
+Landroid/content/pm/ParceledListSlice;-><init>(Ljava/util/List;)V
+Landroid/content/pm/BaseParceledListSlice;-><init>(Ljava/util/List;)V
+Lcom/android/internal/app/procstats/AssociationState$SourceState;->trackProcState(IIJ)V
+Landroid/content/Intent;->resolveTypeIfNeeded(Landroid/content/ContentResolver;)Ljava/lang/String;
+Landroid/net/Uri$Part;->fromEncoded(Ljava/lang/String;)Landroid/net/Uri$Part;
+Landroid/os/MessageQueue;->hasMessages(Landroid/os/Handler;Ljava/lang/Runnable;Ljava/lang/Object;)Z
+Lcom/android/internal/app/procstats/AssociationState$SourceState;->getAssociationState()Lcom/android/internal/app/procstats/AssociationState;
+Lcom/android/internal/app/procstats/AssociationState;->getProcess()Lcom/android/internal/app/procstats/ProcessState;
+Lcom/android/internal/app/procstats/ProcessState;->getCombinedState()I
+Lcom/android/internal/app/procstats/AssociationState$SourceState;->startActive(J)V
+Landroid/net/Uri$1;->createFromParcel(Landroid/os/Parcel;)Ljava/lang/Object;
+Landroid/net/Uri$1;->createFromParcel(Landroid/os/Parcel;)Landroid/net/Uri;
+Landroid/content/Intent;->getSelector()Landroid/content/Intent;
+Lcom/android/internal/os/BatteryStatsImpl$StopwatchTimer;->startRunningLocked(J)V
+Lcom/android/internal/app/ProcessMap;->get(Ljava/lang/String;I)Ljava/lang/Object;
+Landroid/app/IApplicationThread$Stub;->asInterface(Landroid/os/IBinder;)Landroid/app/IApplicationThread;
+Landroid/app/IApplicationThread$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
+Lcom/android/internal/os/BatteryStatsImpl$DurationTimer;->startRunningLocked(J)V
+Lcom/android/internal/os/BatteryStatsImpl$StopwatchTimer;->stopRunningLocked(J)V
+Landroid/net/Uri$Part;-><init>(Ljava/lang/String;Ljava/lang/String;)V
+Lcom/android/internal/os/BatteryStatsImpl$DurationTimer;->stopRunningLocked(J)V
+Lcom/android/internal/os/BatteryStatsImpl;->mapUid(I)I
+Landroid/content/Intent;->hasFileDescriptors()Z
+Landroid/content/pm/ComponentInfo;-><init>(Landroid/content/pm/ComponentInfo;)V
+Landroid/os/ZygoteProcess;->zygoteSendArgsAndGetResult(Landroid/os/ZygoteProcess$ZygoteState;ZLjava/util/ArrayList;)Landroid/os/Process$ProcessStartResult;
+Landroid/os/Handler;->obtainMessage(III)Landroid/os/Message;
+Landroid/os/BaseBundle;->getBoolean(Ljava/lang/String;)Z
+Landroid/view/DisplayCutout$ParcelableWrapper;->writeCutoutToParcel(Landroid/view/DisplayCutout;Landroid/os/Parcel;I)V
+Landroid/view/DisplayAddress$Physical;->writeToParcel(Landroid/os/Parcel;I)V
+Lcom/android/internal/os/BatteryStatsImpl;->getUidStatsLocked(I)Lcom/android/internal/os/BatteryStatsImpl$Uid;
+Landroid/content/pm/ResolveInfo;-><init>()V
+Landroid/util/KeyValueListParser$IntValue;->getValue()I
+Landroid/os/Parcel;->writeList(Ljava/util/List;)V
+Landroid/view/SurfaceControl;->checkNotReleased()V
+Landroid/content/pm/IPackageManager$Stub;->onTransact(ILandroid/os/Parcel;Landroid/os/Parcel;I)Z
+Landroid/os/IPowerManager$Stub;->onTransact(ILandroid/os/Parcel;Landroid/os/Parcel;I)Z
+Landroid/graphics/Rect;->writeToParcel(Landroid/os/Parcel;I)V
+Landroid/content/pm/ParceledListSlice;->getList()Ljava/util/List;
+Landroid/content/pm/BaseParceledListSlice;->getList()Ljava/util/List;
+Landroid/os/Parcel;->writeBoolean(Z)V
+Landroid/telecom/PhoneAccount;->hasCapabilities(I)Z
+Landroid/content/IIntentReceiver$Stub;->asInterface(Landroid/os/IBinder;)Landroid/content/IIntentReceiver;
+Landroid/os/BaseBundle;->isParcelled()Z
+Landroid/os/PowerSaveState$Builder;-><init>()V
+Landroid/os/PowerSaveState$Builder;->setGlobalBatterySaverEnabled(Z)Landroid/os/PowerSaveState$Builder;
+Landroid/os/PowerSaveState$Builder;->setBatterySaverEnabled(Z)Landroid/os/PowerSaveState$Builder;
+Landroid/os/PowerSaveState$Builder;->build()Landroid/os/PowerSaveState;
+Landroid/os/PowerSaveState;-><init>(Landroid/os/PowerSaveState$Builder;)V
+Landroid/os/PowerSaveState$Builder;->access$000(Landroid/os/PowerSaveState$Builder;)Z
+Landroid/os/PowerSaveState$Builder;->access$100(Landroid/os/PowerSaveState$Builder;)I
+Landroid/os/PowerSaveState$Builder;->access$200(Landroid/os/PowerSaveState$Builder;)F
+Landroid/os/PowerSaveState$Builder;->access$300(Landroid/os/PowerSaveState$Builder;)Z
+Lcom/android/internal/os/BatteryStatsImpl$Uid;->createAggregatedPartialWakelockTimerLocked()Lcom/android/internal/os/BatteryStatsImpl$DualTimer;
+Landroid/content/pm/ApplicationInfo;->writeToParcel(Landroid/os/Parcel;I)V
+Landroid/os/Parcel;->writeSparseArray(Landroid/util/SparseArray;)V
+Landroid/os/PowerSaveState$Builder;->setBrightnessFactor(F)Landroid/os/PowerSaveState$Builder;
+Landroid/hardware/display/DisplayManagerInternal$DisplayPowerRequest;->equals(Landroid/hardware/display/DisplayManagerInternal$DisplayPowerRequest;)Z
+Landroid/hardware/display/DisplayManagerInternal$DisplayPowerRequest;->floatEquals(FF)Z
+Landroid/view/Choreographer;->doCallbacks(IJ)V
+Lcom/android/internal/os/BatteryStatsImpl$DualTimer;->startRunningLocked(J)V
+Landroid/graphics/Point;->set(II)V
+Landroid/view/SurfaceControl;->access$800(Landroid/view/SurfaceControl;)V
+Landroid/graphics/Point;->equals(Ljava/lang/Object;)Z
+Lcom/android/internal/os/BatteryStatsImpl;->getPowerManagerWakeLockLevel(I)I
+Landroid/content/Context;->getSystemService(Ljava/lang/Class;)Ljava/lang/Object;
+Landroid/app/ContextImpl;->getSystemServiceName(Ljava/lang/Class;)Ljava/lang/String;
+Landroid/app/SystemServiceRegistry;->getSystemServiceName(Ljava/lang/Class;)Ljava/lang/String;
+Lcom/android/internal/os/BatteryStatsImpl$DualTimer;->stopRunningLocked(J)V
+Landroid/app/AppOpsManager;->getToken(Lcom/android/internal/app/IAppOpsService;)Landroid/os/IBinder;
+Landroid/os/Bundle;->forPair(Ljava/lang/String;Ljava/lang/String;)Landroid/os/Bundle;
+Landroid/os/Bundle;-><init>(I)V
+Landroid/os/BaseBundle;-><init>(I)V
+Landroid/os/HwParcel;-><init>()V
+Landroid/view/SurfaceControl$Transaction;->merge(Landroid/view/SurfaceControl$Transaction;)Landroid/view/SurfaceControl$Transaction;
+Landroid/view/SurfaceControl;->access$4100(JJ)V
+Landroid/view/Choreographer$CallbackQueue;->extractDueCallbacksLocked(J)Landroid/view/Choreographer$CallbackRecord;
+Landroid/graphics/Rect;->offset(II)V
+Landroid/os/PowerManager;->validateWakeLockParameters(ILjava/lang/String;)V
+Landroid/app/AppOpsManager;->checkPackage(ILjava/lang/String;)V
+Landroid/util/SparseArray;->indexOfKey(I)I
+Landroid/content/Intent;->resolveType(Landroid/content/ContentResolver;)Ljava/lang/String;
+Lcom/android/internal/os/BatteryStatsImpl;->noteStartWakeLocked(IILandroid/os/WorkSource$WorkChain;Ljava/lang/String;Ljava/lang/String;IZJJ)V
+Lcom/android/internal/os/BatteryStatsImpl;->aggregateLastWakeupUptimeLocked(J)V
+Lcom/android/internal/os/BatteryStatsImpl$Uid;->noteStartWakeLocked(ILjava/lang/String;IJ)V
+Lcom/android/internal/os/BatteryStatsImpl$OverflowArrayMap;->startObject(Ljava/lang/String;)Ljava/lang/Object;
+Lcom/android/internal/os/BatteryStatsImpl$Uid;->getPidStatsLocked(I)Landroid/os/BatteryStats$Uid$Pid;
+Landroid/content/ComponentName;->writeToParcel(Landroid/content/ComponentName;Landroid/os/Parcel;)V
+Landroid/content/ContextWrapper;->getContentResolver()Landroid/content/ContentResolver;
+Landroid/content/Intent;->writeToParcel(Landroid/os/Parcel;I)V
+Landroid/content/res/Resources;->getBoolean(I)Z
+Landroid/net/Uri;->writeToParcel(Landroid/os/Parcel;Landroid/net/Uri;)V
+Landroid/view/InsetsSource;->getType()I
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 61e2ae9..f4df6b7 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -808,7 +808,9 @@
/*package*/ ActivityInfo mActivityInfo;
@UnsupportedAppUsage
/*package*/ ActivityThread mMainThread;
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(trackingBug = 137825207, maxTargetSdk = Build.VERSION_CODES.Q,
+ publicAlternatives = "Use {@code androidx.fragment.app.Fragment} and "
+ + "{@code androidx.fragment.app.FragmentManager} instead")
Activity mParent;
@UnsupportedAppUsage
boolean mCalled;
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 50f945b..553ef69 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -2492,13 +2492,15 @@
}
}
- private static final String HEAP_FULL_COLUMN
- = "%13s %8s %8s %8s %8s %8s %8s %8s %8s %8s %8s";
- private static final String HEAP_COLUMN
- = "%13s %8s %8s %8s %8s %8s %8s %8s";
+ private static final String HEAP_FULL_COLUMN =
+ "%13s %8s %8s %8s %8s %8s %8s %8s %8s %8s %8s %8s";
+ private static final String HEAP_COLUMN =
+ "%13s %8s %8s %8s %8s %8s %8s %8s %8s";
private static final String ONE_COUNT_COLUMN = "%21s %8d";
private static final String TWO_COUNT_COLUMNS = "%21s %8d %21s %8d";
- private static final String ONE_COUNT_COLUMN_HEADER = "%21s %8s";
+ private static final String THREE_COUNT_COLUMNS = "%21s %8d %21s %8s %21s %8d";
+ private static final String TWO_COUNT_COLUMN_HEADER = "%21s %8s %21s %8s";
+ private static final String ONE_ALT_COUNT_COLUMN = "%21s %8s %21s %8d";
// Formatting for checkin service - update version if row format changes
private static final int ACTIVITY_THREAD_CHECKIN_VERSION = 4;
@@ -2619,43 +2621,43 @@
if (dumpFullInfo) {
printRow(pw, HEAP_FULL_COLUMN, "", "Pss", "Pss", "Shared", "Private",
"Shared", "Private", memInfo.hasSwappedOutPss ? "SwapPss" : "Swap",
- "Heap", "Heap", "Heap");
+ "Rss", "Heap", "Heap", "Heap");
printRow(pw, HEAP_FULL_COLUMN, "", "Total", "Clean", "Dirty", "Dirty",
- "Clean", "Clean", "Dirty",
+ "Clean", "Clean", "Dirty", "Total",
"Size", "Alloc", "Free");
printRow(pw, HEAP_FULL_COLUMN, "", "------", "------", "------", "------",
- "------", "------", "------", "------", "------", "------");
+ "------", "------", "------", "------", "------", "------", "------");
printRow(pw, HEAP_FULL_COLUMN, "Native Heap", memInfo.nativePss,
memInfo.nativeSwappablePss, memInfo.nativeSharedDirty,
memInfo.nativePrivateDirty, memInfo.nativeSharedClean,
memInfo.nativePrivateClean, memInfo.hasSwappedOutPss ?
memInfo.nativeSwappedOutPss : memInfo.nativeSwappedOut,
- nativeMax, nativeAllocated, nativeFree);
+ memInfo.nativeRss, nativeMax, nativeAllocated, nativeFree);
printRow(pw, HEAP_FULL_COLUMN, "Dalvik Heap", memInfo.dalvikPss,
memInfo.dalvikSwappablePss, memInfo.dalvikSharedDirty,
memInfo.dalvikPrivateDirty, memInfo.dalvikSharedClean,
memInfo.dalvikPrivateClean, memInfo.hasSwappedOutPss ?
memInfo.dalvikSwappedOutPss : memInfo.dalvikSwappedOut,
- dalvikMax, dalvikAllocated, dalvikFree);
+ memInfo.dalvikRss, dalvikMax, dalvikAllocated, dalvikFree);
} else {
printRow(pw, HEAP_COLUMN, "", "Pss", "Private",
"Private", memInfo.hasSwappedOutPss ? "SwapPss" : "Swap",
- "Heap", "Heap", "Heap");
+ "Rss", "Heap", "Heap", "Heap");
printRow(pw, HEAP_COLUMN, "", "Total", "Dirty",
- "Clean", "Dirty", "Size", "Alloc", "Free");
+ "Clean", "Dirty", "Total", "Size", "Alloc", "Free");
printRow(pw, HEAP_COLUMN, "", "------", "------", "------",
- "------", "------", "------", "------", "------");
+ "------", "------", "------", "------", "------", "------");
printRow(pw, HEAP_COLUMN, "Native Heap", memInfo.nativePss,
memInfo.nativePrivateDirty,
memInfo.nativePrivateClean,
memInfo.hasSwappedOutPss ? memInfo.nativeSwappedOutPss :
- memInfo.nativeSwappedOut,
+ memInfo.nativeSwappedOut, memInfo.nativeRss,
nativeMax, nativeAllocated, nativeFree);
printRow(pw, HEAP_COLUMN, "Dalvik Heap", memInfo.dalvikPss,
memInfo.dalvikPrivateDirty,
memInfo.dalvikPrivateClean,
memInfo.hasSwappedOutPss ? memInfo.dalvikSwappedOutPss :
- memInfo.dalvikSwappedOut,
+ memInfo.dalvikSwappedOut, memInfo.dalvikRss,
dalvikMax, dalvikAllocated, dalvikFree);
}
@@ -2667,6 +2669,7 @@
int otherPrivateClean = memInfo.otherPrivateClean;
int otherSwappedOut = memInfo.otherSwappedOut;
int otherSwappedOutPss = memInfo.otherSwappedOutPss;
+ int otherRss = memInfo.otherRss;
for (int i=0; i<Debug.MemoryInfo.NUM_OTHER_STATS; i++) {
final int myPss = memInfo.getOtherPss(i);
@@ -2677,21 +2680,22 @@
final int myPrivateClean = memInfo.getOtherPrivateClean(i);
final int mySwappedOut = memInfo.getOtherSwappedOut(i);
final int mySwappedOutPss = memInfo.getOtherSwappedOutPss(i);
+ final int myRss = memInfo.getOtherRss(i);
if (myPss != 0 || mySharedDirty != 0 || myPrivateDirty != 0
- || mySharedClean != 0 || myPrivateClean != 0
+ || mySharedClean != 0 || myPrivateClean != 0 || myRss != 0
|| (memInfo.hasSwappedOutPss ? mySwappedOutPss : mySwappedOut) != 0) {
if (dumpFullInfo) {
printRow(pw, HEAP_FULL_COLUMN, Debug.MemoryInfo.getOtherLabel(i),
myPss, mySwappablePss, mySharedDirty, myPrivateDirty,
mySharedClean, myPrivateClean,
memInfo.hasSwappedOutPss ? mySwappedOutPss : mySwappedOut,
- "", "", "");
+ myRss, "", "", "");
} else {
printRow(pw, HEAP_COLUMN, Debug.MemoryInfo.getOtherLabel(i),
myPss, myPrivateDirty,
myPrivateClean,
memInfo.hasSwappedOutPss ? mySwappedOutPss : mySwappedOut,
- "", "", "");
+ myRss, "", "", "");
}
otherPss -= myPss;
otherSwappablePss -= mySwappablePss;
@@ -2701,6 +2705,7 @@
otherPrivateClean -= myPrivateClean;
otherSwappedOut -= mySwappedOut;
otherSwappedOutPss -= mySwappedOutPss;
+ otherRss -= myRss;
}
}
@@ -2708,25 +2713,25 @@
printRow(pw, HEAP_FULL_COLUMN, "Unknown", otherPss, otherSwappablePss,
otherSharedDirty, otherPrivateDirty, otherSharedClean, otherPrivateClean,
memInfo.hasSwappedOutPss ? otherSwappedOutPss : otherSwappedOut,
- "", "", "");
+ otherRss, "", "", "");
printRow(pw, HEAP_FULL_COLUMN, "TOTAL", memInfo.getTotalPss(),
memInfo.getTotalSwappablePss(),
memInfo.getTotalSharedDirty(), memInfo.getTotalPrivateDirty(),
memInfo.getTotalSharedClean(), memInfo.getTotalPrivateClean(),
memInfo.hasSwappedOutPss ? memInfo.getTotalSwappedOutPss() :
- memInfo.getTotalSwappedOut(),
+ memInfo.getTotalSwappedOut(), memInfo.getTotalRss(),
nativeMax+dalvikMax, nativeAllocated+dalvikAllocated,
nativeFree+dalvikFree);
} else {
printRow(pw, HEAP_COLUMN, "Unknown", otherPss,
otherPrivateDirty, otherPrivateClean,
memInfo.hasSwappedOutPss ? otherSwappedOutPss : otherSwappedOut,
- "", "", "");
+ otherRss, "", "", "");
printRow(pw, HEAP_COLUMN, "TOTAL", memInfo.getTotalPss(),
memInfo.getTotalPrivateDirty(),
memInfo.getTotalPrivateClean(),
memInfo.hasSwappedOutPss ? memInfo.getTotalSwappedOutPss() :
- memInfo.getTotalSwappedOut(),
+ memInfo.getTotalSwappedOut(), memInfo.getTotalPss(),
nativeMax+dalvikMax,
nativeAllocated+dalvikAllocated, nativeFree+dalvikFree);
}
@@ -2745,6 +2750,7 @@
final int myPrivateClean = memInfo.getOtherPrivateClean(i);
final int mySwappedOut = memInfo.getOtherSwappedOut(i);
final int mySwappedOutPss = memInfo.getOtherSwappedOutPss(i);
+ final int myRss = memInfo.getOtherRss(i);
if (myPss != 0 || mySharedDirty != 0 || myPrivateDirty != 0
|| mySharedClean != 0 || myPrivateClean != 0
|| (memInfo.hasSwappedOutPss ? mySwappedOutPss : mySwappedOut) != 0) {
@@ -2753,13 +2759,13 @@
myPss, mySwappablePss, mySharedDirty, myPrivateDirty,
mySharedClean, myPrivateClean,
memInfo.hasSwappedOutPss ? mySwappedOutPss : mySwappedOut,
- "", "", "");
+ myRss, "", "", "");
} else {
printRow(pw, HEAP_COLUMN, Debug.MemoryInfo.getOtherLabel(i),
myPss, myPrivateDirty,
myPrivateClean,
memInfo.hasSwappedOutPss ? mySwappedOutPss : mySwappedOut,
- "", "", "");
+ myRss, "", "", "");
}
}
}
@@ -2768,31 +2774,36 @@
pw.println(" ");
pw.println(" App Summary");
- printRow(pw, ONE_COUNT_COLUMN_HEADER, "", "Pss(KB)");
- printRow(pw, ONE_COUNT_COLUMN_HEADER, "", "------");
+ printRow(pw, TWO_COUNT_COLUMN_HEADER, "", "Pss(KB)", "", "Rss(KB)");
+ printRow(pw, TWO_COUNT_COLUMN_HEADER, "", "------", "", "------");
+ printRow(pw, TWO_COUNT_COLUMNS,
+ "Java Heap:", memInfo.getSummaryJavaHeap(), "", memInfo.getSummaryJavaHeapRss());
+ printRow(pw, TWO_COUNT_COLUMNS,
+ "Native Heap:", memInfo.getSummaryNativeHeap(), "",
+ memInfo.getSummaryNativeHeapRss());
+ printRow(pw, TWO_COUNT_COLUMNS,
+ "Code:", memInfo.getSummaryCode(), "", memInfo.getSummaryCodeRss());
+ printRow(pw, TWO_COUNT_COLUMNS,
+ "Stack:", memInfo.getSummaryStack(), "", memInfo.getSummaryStackRss());
+ printRow(pw, TWO_COUNT_COLUMNS,
+ "Graphics:", memInfo.getSummaryGraphics(), "", memInfo.getSummaryGraphicsRss());
printRow(pw, ONE_COUNT_COLUMN,
- "Java Heap:", memInfo.getSummaryJavaHeap());
+ "Private Other:", memInfo.getSummaryPrivateOther());
printRow(pw, ONE_COUNT_COLUMN,
- "Native Heap:", memInfo.getSummaryNativeHeap());
- printRow(pw, ONE_COUNT_COLUMN,
- "Code:", memInfo.getSummaryCode());
- printRow(pw, ONE_COUNT_COLUMN,
- "Stack:", memInfo.getSummaryStack());
- printRow(pw, ONE_COUNT_COLUMN,
- "Graphics:", memInfo.getSummaryGraphics());
- printRow(pw, ONE_COUNT_COLUMN,
- "Private Other:", memInfo.getSummaryPrivateOther());
- printRow(pw, ONE_COUNT_COLUMN,
- "System:", memInfo.getSummarySystem());
+ "System:", memInfo.getSummarySystem());
+ printRow(pw, ONE_ALT_COUNT_COLUMN,
+ "Unknown:", "", "", memInfo.getSummaryUnknownRss());
pw.println(" ");
if (memInfo.hasSwappedOutPss) {
- printRow(pw, TWO_COUNT_COLUMNS,
- "TOTAL:", memInfo.getSummaryTotalPss(),
- "TOTAL SWAP PSS:", memInfo.getSummaryTotalSwapPss());
+ printRow(pw, THREE_COUNT_COLUMNS,
+ "TOTAL PSS:", memInfo.getSummaryTotalPss(),
+ "TOTAL RSS:", memInfo.getTotalRss(),
+ "TOTAL SWAP PSS:", memInfo.getSummaryTotalSwapPss());
} else {
- printRow(pw, TWO_COUNT_COLUMNS,
- "TOTAL:", memInfo.getSummaryTotalPss(),
- "TOTAL SWAP (KB):", memInfo.getSummaryTotalSwap());
+ printRow(pw, THREE_COUNT_COLUMNS,
+ "TOTAL PSS:", memInfo.getSummaryTotalPss(),
+ "TOTAL RSS:", memInfo.getTotalRss(),
+ "TOTAL SWAP (KB):", memInfo.getSummaryTotalSwap());
}
}
@@ -2804,7 +2815,7 @@
private static void dumpMemoryInfo(ProtoOutputStream proto, long fieldId, String name,
int pss, int cleanPss, int sharedDirty, int privateDirty,
int sharedClean, int privateClean,
- boolean hasSwappedOutPss, int dirtySwap, int dirtySwapPss) {
+ boolean hasSwappedOutPss, int dirtySwap, int dirtySwapPss, int rss) {
final long token = proto.start(fieldId);
proto.write(MemInfoDumpProto.ProcessMemory.MemoryInfo.NAME, name);
@@ -2819,6 +2830,7 @@
} else {
proto.write(MemInfoDumpProto.ProcessMemory.MemoryInfo.DIRTY_SWAP_KB, dirtySwap);
}
+ proto.write(MemInfoDumpProto.ProcessMemory.MemoryInfo.TOTAL_RSS_KB, rss);
proto.end(token);
}
@@ -2837,7 +2849,8 @@
memInfo.nativePss, memInfo.nativeSwappablePss, memInfo.nativeSharedDirty,
memInfo.nativePrivateDirty, memInfo.nativeSharedClean,
memInfo.nativePrivateClean, memInfo.hasSwappedOutPss,
- memInfo.nativeSwappedOut, memInfo.nativeSwappedOutPss);
+ memInfo.nativeSwappedOut, memInfo.nativeSwappedOutPss,
+ memInfo.nativeRss);
proto.write(MemInfoDumpProto.ProcessMemory.HeapInfo.HEAP_SIZE_KB, nativeMax);
proto.write(MemInfoDumpProto.ProcessMemory.HeapInfo.HEAP_ALLOC_KB, nativeAllocated);
proto.write(MemInfoDumpProto.ProcessMemory.HeapInfo.HEAP_FREE_KB, nativeFree);
@@ -2848,7 +2861,8 @@
memInfo.dalvikPss, memInfo.dalvikSwappablePss, memInfo.dalvikSharedDirty,
memInfo.dalvikPrivateDirty, memInfo.dalvikSharedClean,
memInfo.dalvikPrivateClean, memInfo.hasSwappedOutPss,
- memInfo.dalvikSwappedOut, memInfo.dalvikSwappedOutPss);
+ memInfo.dalvikSwappedOut, memInfo.dalvikSwappedOutPss,
+ memInfo.dalvikRss);
proto.write(MemInfoDumpProto.ProcessMemory.HeapInfo.HEAP_SIZE_KB, dalvikMax);
proto.write(MemInfoDumpProto.ProcessMemory.HeapInfo.HEAP_ALLOC_KB, dalvikAllocated);
proto.write(MemInfoDumpProto.ProcessMemory.HeapInfo.HEAP_FREE_KB, dalvikFree);
@@ -2862,6 +2876,7 @@
int otherPrivateClean = memInfo.otherPrivateClean;
int otherSwappedOut = memInfo.otherSwappedOut;
int otherSwappedOutPss = memInfo.otherSwappedOutPss;
+ int otherRss = memInfo.otherRss;
for (int i = 0; i < Debug.MemoryInfo.NUM_OTHER_STATS; i++) {
final int myPss = memInfo.getOtherPss(i);
@@ -2872,14 +2887,15 @@
final int myPrivateClean = memInfo.getOtherPrivateClean(i);
final int mySwappedOut = memInfo.getOtherSwappedOut(i);
final int mySwappedOutPss = memInfo.getOtherSwappedOutPss(i);
+ final int myRss = memInfo.getOtherRss(i);
if (myPss != 0 || mySharedDirty != 0 || myPrivateDirty != 0
- || mySharedClean != 0 || myPrivateClean != 0
+ || mySharedClean != 0 || myPrivateClean != 0 || myRss != 0
|| (memInfo.hasSwappedOutPss ? mySwappedOutPss : mySwappedOut) != 0) {
dumpMemoryInfo(proto, MemInfoDumpProto.ProcessMemory.OTHER_HEAPS,
Debug.MemoryInfo.getOtherLabel(i),
myPss, mySwappablePss, mySharedDirty, myPrivateDirty,
mySharedClean, myPrivateClean,
- memInfo.hasSwappedOutPss, mySwappedOut, mySwappedOutPss);
+ memInfo.hasSwappedOutPss, mySwappedOut, mySwappedOutPss, myRss);
otherPss -= myPss;
otherSwappablePss -= mySwappablePss;
@@ -2889,20 +2905,21 @@
otherPrivateClean -= myPrivateClean;
otherSwappedOut -= mySwappedOut;
otherSwappedOutPss -= mySwappedOutPss;
+ otherRss -= myRss;
}
}
dumpMemoryInfo(proto, MemInfoDumpProto.ProcessMemory.UNKNOWN_HEAP, "Unknown",
otherPss, otherSwappablePss,
otherSharedDirty, otherPrivateDirty, otherSharedClean, otherPrivateClean,
- memInfo.hasSwappedOutPss, otherSwappedOut, otherSwappedOutPss);
+ memInfo.hasSwappedOutPss, otherSwappedOut, otherSwappedOutPss, otherRss);
final long tToken = proto.start(MemInfoDumpProto.ProcessMemory.TOTAL_HEAP);
dumpMemoryInfo(proto, MemInfoDumpProto.ProcessMemory.HeapInfo.MEM_INFO, "TOTAL",
memInfo.getTotalPss(), memInfo.getTotalSwappablePss(),
memInfo.getTotalSharedDirty(), memInfo.getTotalPrivateDirty(),
memInfo.getTotalSharedClean(), memInfo.getTotalPrivateClean(),
memInfo.hasSwappedOutPss, memInfo.getTotalSwappedOut(),
- memInfo.getTotalSwappedOutPss());
+ memInfo.getTotalSwappedOutPss(), memInfo.getTotalRss());
proto.write(MemInfoDumpProto.ProcessMemory.HeapInfo.HEAP_SIZE_KB,
nativeMax + dalvikMax);
proto.write(MemInfoDumpProto.ProcessMemory.HeapInfo.HEAP_ALLOC_KB,
@@ -2923,6 +2940,7 @@
final int myPrivateClean = memInfo.getOtherPrivateClean(i);
final int mySwappedOut = memInfo.getOtherSwappedOut(i);
final int mySwappedOutPss = memInfo.getOtherSwappedOutPss(i);
+ final int myRss = memInfo.getOtherRss(i);
if (myPss != 0 || mySharedDirty != 0 || myPrivateDirty != 0
|| mySharedClean != 0 || myPrivateClean != 0
|| (memInfo.hasSwappedOutPss ? mySwappedOutPss : mySwappedOut) != 0) {
@@ -2930,7 +2948,7 @@
Debug.MemoryInfo.getOtherLabel(i),
myPss, mySwappablePss, mySharedDirty, myPrivateDirty,
mySharedClean, myPrivateClean,
- memInfo.hasSwappedOutPss, mySwappedOut, mySwappedOutPss);
+ memInfo.hasSwappedOutPss, mySwappedOut, mySwappedOutPss, myRss);
}
}
}
@@ -2958,6 +2976,19 @@
proto.write(MemInfoDumpProto.ProcessMemory.AppSummary.TOTAL_SWAP_PSS,
memInfo.getSummaryTotalSwap());
}
+ proto.write(MemInfoDumpProto.ProcessMemory.AppSummary.JAVA_HEAP_RSS_KB,
+ memInfo.getSummaryJavaHeapRss());
+ proto.write(MemInfoDumpProto.ProcessMemory.AppSummary.NATIVE_HEAP_RSS_KB,
+ memInfo.getSummaryNativeHeapRss());
+ proto.write(MemInfoDumpProto.ProcessMemory.AppSummary.CODE_RSS_KB,
+ memInfo.getSummaryCodeRss());
+ proto.write(MemInfoDumpProto.ProcessMemory.AppSummary.STACK_RSS_KB,
+ memInfo.getSummaryStackRss());
+ proto.write(MemInfoDumpProto.ProcessMemory.AppSummary.GRAPHICS_RSS_KB,
+ memInfo.getSummaryGraphicsRss());
+ proto.write(MemInfoDumpProto.ProcessMemory.AppSummary.UNKNOWN_RSS_KB,
+ memInfo.getSummaryUnknownRss());
+
proto.end(asToken);
}
diff --git a/core/java/android/app/ActivityView.java b/core/java/android/app/ActivityView.java
index 415ec64..e891828 100644
--- a/core/java/android/app/ActivityView.java
+++ b/core/java/android/app/ActivityView.java
@@ -120,8 +120,10 @@
mActivityTaskManager = ActivityTaskManager.getService();
mSurfaceView = new SurfaceView(context);
+ // Since ActivityView#getAlpha has been overridden, we should use parent class's alpha
+ // as master to synchronize surface view's alpha value.
+ mSurfaceView.setAlpha(super.getAlpha());
mSurfaceView.setUseAlpha();
- mSurfaceView.setAlpha(0f);
mSurfaceCallback = new SurfaceCallback();
mSurfaceView.getHolder().addCallback(mSurfaceCallback);
addView(mSurfaceView);
@@ -348,9 +350,20 @@
mSurfaceView.layout(0 /* left */, 0 /* top */, r - l /* right */, b - t /* bottom */);
}
+ /**
+ * Sets the alpha value when the content of {@link SurfaceView} needs to show or hide.
+ * <p>Note: The surface view may ignore the alpha value in some cases. Refer to
+ * {@link SurfaceView#setAlpha} for more details.
+ *
+ * @param alpha The opacity of the view.
+ */
@Override
public void setAlpha(float alpha) {
- mSurfaceView.setAlpha(alpha);
+ super.setAlpha(alpha);
+
+ if (mSurfaceView != null) {
+ mSurfaceView.setAlpha(alpha);
+ }
}
@Override
diff --git a/core/java/android/app/DisabledWallpaperManager.java b/core/java/android/app/DisabledWallpaperManager.java
new file mode 100644
index 0000000..5185941
--- /dev/null
+++ b/core/java/android/app/DisabledWallpaperManager.java
@@ -0,0 +1,346 @@
+/*
+ * 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.app;
+
+import android.annotation.NonNull;
+import android.content.ComponentName;
+import android.content.Intent;
+import android.graphics.Bitmap;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.ParcelFileDescriptor;
+import android.util.Log;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * A no-op implementation of {@link WallpaperManager}.
+ */
+final class DisabledWallpaperManager extends WallpaperManager {
+
+ private static final String TAG = DisabledWallpaperManager.class.getSimpleName();
+
+ // Don't need to worry about synchronization
+ private static DisabledWallpaperManager sInstance;
+
+ // TODO(b/138939803): STOPSHIP changed to false and/or remove it
+ private static final boolean DEBUG = true;
+
+ @NonNull
+ static DisabledWallpaperManager getInstance() {
+ if (sInstance == null) {
+ sInstance = new DisabledWallpaperManager();
+ }
+ return sInstance;
+ }
+
+ private DisabledWallpaperManager() {
+ super(null, null, null);
+ }
+
+ @Override
+ public boolean isWallpaperSupported() {
+ return false;
+ }
+
+ @Override
+ public boolean isSetWallpaperAllowed() {
+ return false;
+ }
+
+ // TODO(b/138939803): STOPSHIP methods below should not be necessary,
+ // callers should check if isWallpaperSupported(), consider removing them to keep this class
+ // simpler
+
+ private static <T> T unsupported() {
+ if (DEBUG) Log.w(TAG, "unsupported method called; returning null", new Exception());
+ return null;
+ }
+
+ private static boolean unsupportedBoolean() {
+ if (DEBUG) Log.w(TAG, "unsupported method called; returning false", new Exception());
+ return false;
+ }
+
+ @Override
+ public Drawable getDrawable() {
+ return unsupported();
+ }
+
+ @Override
+ public Drawable getBuiltInDrawable() {
+ return unsupported();
+ }
+
+ @Override
+ public Drawable getBuiltInDrawable(int which) {
+ return unsupported();
+ }
+
+ @Override
+ public Drawable getBuiltInDrawable(int outWidth, int outHeight, boolean scaleToFit,
+ float horizontalAlignment, float verticalAlignment) {
+ return unsupported();
+ }
+
+ @Override
+ public Drawable getBuiltInDrawable(int outWidth, int outHeight, boolean scaleToFit,
+ float horizontalAlignment, float verticalAlignment, int which) {
+ return unsupported();
+ }
+
+ @Override
+ public Drawable peekDrawable() {
+ return unsupported();
+ }
+
+ @Override
+ public Drawable getFastDrawable() {
+ return unsupported();
+ }
+
+ @Override
+ public Drawable peekFastDrawable() {
+ return unsupported();
+ }
+
+ @Override
+ public Bitmap getBitmap() {
+ return unsupported();
+ }
+
+ @Override
+ public Bitmap getBitmap(boolean hardware) {
+ return unsupported();
+ }
+
+ @Override
+ public Bitmap getBitmapAsUser(int userId, boolean hardware) {
+ return unsupported();
+ }
+
+ @Override
+ public ParcelFileDescriptor getWallpaperFile(int which) {
+ return unsupported();
+ }
+
+ @Override
+ public void addOnColorsChangedListener(OnColorsChangedListener listener, Handler handler) {
+ unsupported();
+ }
+
+ @Override
+ public void addOnColorsChangedListener(OnColorsChangedListener listener, Handler handler,
+ int userId) {
+ unsupported();
+ }
+
+ @Override
+ public void removeOnColorsChangedListener(OnColorsChangedListener callback) {
+ unsupported();
+ }
+
+ @Override
+ public void removeOnColorsChangedListener(OnColorsChangedListener callback, int userId) {
+ unsupported();
+ }
+
+ @Override
+ public WallpaperColors getWallpaperColors(int which) {
+ return unsupported();
+ }
+
+ @Override
+ public WallpaperColors getWallpaperColors(int which, int userId) {
+ return unsupported();
+ }
+
+ @Override
+ public ParcelFileDescriptor getWallpaperFile(int which, int userId) {
+ return unsupported();
+ }
+
+ @Override
+ public void forgetLoadedWallpaper() {
+ unsupported();
+ }
+
+ @Override
+ public WallpaperInfo getWallpaperInfo() {
+ return unsupported();
+ }
+
+ @Override
+ public WallpaperInfo getWallpaperInfo(int userId) {
+ return unsupported();
+ }
+
+ @Override
+ public int getWallpaperId(int which) {
+ return unsupported();
+ }
+
+ @Override
+ public int getWallpaperIdForUser(int which, int userId) {
+ return unsupported();
+ }
+
+ @Override
+ public Intent getCropAndSetWallpaperIntent(Uri imageUri) {
+ return unsupported();
+ }
+
+ @Override
+ public void setResource(int resid) throws IOException {
+ unsupported();
+ }
+
+ @Override
+ public int setResource(int resid, int which) throws IOException {
+ return unsupported();
+ }
+
+ @Override
+ public void setBitmap(Bitmap bitmap) throws IOException {
+ unsupported();
+ }
+
+ @Override
+ public int setBitmap(Bitmap fullImage, Rect visibleCropHint, boolean allowBackup)
+ throws IOException {
+ return unsupported();
+ }
+
+ @Override
+ public int setBitmap(Bitmap fullImage, Rect visibleCropHint, boolean allowBackup, int which)
+ throws IOException {
+ return unsupported();
+ }
+
+ @Override
+ public int setBitmap(Bitmap fullImage, Rect visibleCropHint, boolean allowBackup, int which,
+ int userId) throws IOException {
+ return unsupported();
+ }
+
+ @Override
+ public void setStream(InputStream bitmapData) throws IOException {
+ unsupported();
+ }
+
+ @Override
+ public int setStream(InputStream bitmapData, Rect visibleCropHint, boolean allowBackup)
+ throws IOException {
+ return unsupported();
+ }
+
+ @Override
+ public int setStream(InputStream bitmapData, Rect visibleCropHint, boolean allowBackup,
+ int which) throws IOException {
+ return unsupported();
+ }
+
+ @Override
+ public boolean hasResourceWallpaper(int resid) {
+ return unsupportedBoolean();
+ }
+
+ @Override
+ public int getDesiredMinimumWidth() {
+ return unsupported();
+ }
+
+ @Override
+ public int getDesiredMinimumHeight() {
+ return unsupported();
+ }
+
+ @Override
+ public void suggestDesiredDimensions(int minimumWidth, int minimumHeight) {
+ unsupported();
+ }
+
+ @Override
+ public void setDisplayPadding(Rect padding) {
+ unsupported();
+ }
+
+ @Override
+ public void setDisplayOffset(IBinder windowToken, int x, int y) {
+ unsupported();
+ }
+
+ @Override
+ public void clearWallpaper() {
+ unsupported();
+ }
+
+ @Override
+ public void clearWallpaper(int which, int userId) {
+ unsupported();
+ }
+
+ @Override
+ public boolean setWallpaperComponent(ComponentName name) {
+ return unsupportedBoolean();
+ }
+
+ @Override
+ public boolean setWallpaperComponent(ComponentName name, int userId) {
+ return unsupportedBoolean();
+ }
+
+ @Override
+ public void setWallpaperOffsets(IBinder windowToken, float xOffset, float yOffset) {
+ unsupported();
+ }
+
+ @Override
+ public void setWallpaperOffsetSteps(float xStep, float yStep) {
+ unsupported();
+ }
+
+ @Override
+ public void sendWallpaperCommand(IBinder windowToken, String action, int x, int y, int z,
+ Bundle extras) {
+ unsupported();
+ }
+
+ @Override
+ public void clearWallpaperOffsets(IBinder windowToken) {
+ unsupported();
+ }
+
+ @Override
+ public void clear() throws IOException {
+ unsupported();
+ }
+
+ @Override
+ public void clear(int which) throws IOException {
+ unsupported();
+ }
+
+ @Override
+ public boolean isWallpaperBackupEligible(int which) {
+ return unsupportedBoolean();
+ }
+}
diff --git a/core/java/android/app/ITaskStackListener.aidl b/core/java/android/app/ITaskStackListener.aidl
index 650147b..61867ea 100644
--- a/core/java/android/app/ITaskStackListener.aidl
+++ b/core/java/android/app/ITaskStackListener.aidl
@@ -185,4 +185,9 @@
* @param newDisplayId id of the new display.
*/
void onTaskDisplayChanged(int taskId, int newDisplayId);
+
+ /**
+ * Called when any additions or deletions to the recent tasks list have been made.
+ */
+ void onRecentTaskListUpdated();
}
diff --git a/core/java/android/app/LocalActivityManager.java b/core/java/android/app/LocalActivityManager.java
index 19575b2..87b064d 100644
--- a/core/java/android/app/LocalActivityManager.java
+++ b/core/java/android/app/LocalActivityManager.java
@@ -22,6 +22,7 @@
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.os.Binder;
+import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.view.Window;
@@ -74,23 +75,33 @@
/** Thread our activities are running in. */
private final ActivityThread mActivityThread;
/** The containing activity that owns the activities we create. */
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(trackingBug = 137825207, maxTargetSdk = Build.VERSION_CODES.Q,
+ publicAlternatives = "Use {@code androidx.fragment.app.Fragment} and "
+ + "{@code androidx.fragment.app.FragmentManager} instead")
private final Activity mParent;
/** The activity that is currently resumed. */
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(trackingBug = 137825207, maxTargetSdk = Build.VERSION_CODES.Q,
+ publicAlternatives = "Use {@code androidx.fragment.app.Fragment} and "
+ + "{@code androidx.fragment.app.FragmentManager} instead")
private LocalActivityRecord mResumed;
/** id -> record of all known activities. */
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(trackingBug = 137825207, maxTargetSdk = Build.VERSION_CODES.Q,
+ publicAlternatives = "Use {@code androidx.fragment.app.Fragment} and "
+ + "{@code androidx.fragment.app.FragmentManager} instead")
private final Map<String, LocalActivityRecord> mActivities
= new HashMap<String, LocalActivityRecord>();
/** array of all known activities for easy iterating. */
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(trackingBug = 137825207, maxTargetSdk = Build.VERSION_CODES.Q,
+ publicAlternatives = "Use {@code androidx.fragment.app.Fragment} and "
+ + "{@code androidx.fragment.app.FragmentManager} instead")
private final ArrayList<LocalActivityRecord> mActivityArray
= new ArrayList<LocalActivityRecord>();
/** True if only one activity can be resumed at a time */
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(trackingBug = 137825207, maxTargetSdk = Build.VERSION_CODES.Q,
+ publicAlternatives = "Use {@code androidx.fragment.app.Fragment} and "
+ + "{@code androidx.fragment.app.FragmentManager} instead")
private boolean mSingleMode;
/** Set to true once we find out the container is finishing. */
@@ -117,7 +128,9 @@
mSingleMode = singleMode;
}
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(trackingBug = 137825207, maxTargetSdk = Build.VERSION_CODES.Q,
+ publicAlternatives = "Use {@code androidx.fragment.app.Fragment} and "
+ + "{@code androidx.fragment.app.FragmentManager} instead")
private void moveToState(LocalActivityRecord r, int desiredState) {
if (r.curState == RESTORED || r.curState == DESTROYED) {
// startActivity() has not yet been called, so nothing to do.
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 5034b53..c58972e 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -695,11 +695,22 @@
@Override
public WallpaperManager createService(ContextImpl ctx)
throws ServiceNotFoundException {
- final IBinder b;
- if (ctx.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.P) {
- b = ServiceManager.getServiceOrThrow(Context.WALLPAPER_SERVICE);
- } else {
- b = ServiceManager.getService(Context.WALLPAPER_SERVICE);
+ final IBinder b = ServiceManager.getService(Context.WALLPAPER_SERVICE);
+ if (b == null) {
+ // There are 2 reason service can be null:
+ // 1.Device doesn't support it - that's fine
+ // 2.App is running on instant mode - should fail
+ final boolean enabled = Resources.getSystem()
+ .getBoolean(com.android.internal.R.bool.config_enableWallpaperService);
+ if (!enabled) {
+ // Life moves on...
+ return DisabledWallpaperManager.getInstance();
+ }
+ if (ctx.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.P) {
+ // Instant app
+ throw new ServiceNotFoundException(Context.WALLPAPER_SERVICE);
+ }
+ // Bad state - WallpaperManager methods will throw exception
}
IWallpaperManager service = IWallpaperManager.Stub.asInterface(b);
return new WallpaperManager(service, ctx.getOuterContext(),
diff --git a/core/java/android/app/TaskStackListener.java b/core/java/android/app/TaskStackListener.java
index b63feb5..e3a0e11 100644
--- a/core/java/android/app/TaskStackListener.java
+++ b/core/java/android/app/TaskStackListener.java
@@ -182,4 +182,8 @@
@Override
public void onTaskDisplayChanged(int taskId, int newDisplayId) throws RemoteException {
}
+
+ @Override
+ public void onRecentTaskListUpdated() throws RemoteException {
+ }
}
diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java
index d305238..59ecf4a 100644
--- a/core/java/android/app/WallpaperManager.java
+++ b/core/java/android/app/WallpaperManager.java
@@ -510,7 +510,9 @@
/*package*/ WallpaperManager(IWallpaperManager service, Context context, Handler handler) {
mContext = context;
- initGlobals(service, context.getMainLooper());
+ if (service != null) {
+ initGlobals(service, context.getMainLooper());
+ }
}
/**
diff --git a/core/java/android/app/backup/WallpaperBackupHelper.java b/core/java/android/app/backup/WallpaperBackupHelper.java
index 36f5f96..5c0ddc1 100644
--- a/core/java/android/app/backup/WallpaperBackupHelper.java
+++ b/core/java/android/app/backup/WallpaperBackupHelper.java
@@ -85,6 +85,10 @@
*/
@Override
public void restoreEntity(BackupDataInputStream data) {
+ if (mWpm == null) {
+ Slog.w(TAG, "restoreEntity(): no wallpaper service");
+ return;
+ }
final String key = data.getKey();
if (isKeyInList(key, mKeys)) {
if (key.equals(WALLPAPER_IMAGE_KEY)) {
diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java
index 3c79991..4ea3726 100644
--- a/core/java/android/content/ContentProvider.java
+++ b/core/java/android/content/ContentProvider.java
@@ -2112,6 +2112,10 @@
mSingleUser = (info.flags & ProviderInfo.FLAG_SINGLE_USER) != 0;
setAuthorities(info.authority);
}
+ if (Build.IS_DEBUGGABLE) {
+ setTransportLoggingEnabled(Log.isLoggable(getClass().getSimpleName(),
+ Log.VERBOSE));
+ }
ContentProvider.this.onCreate();
}
}
diff --git a/core/java/android/content/ContentProviderOperation.java b/core/java/android/content/ContentProviderOperation.java
index c201e4d..621f331 100644
--- a/core/java/android/content/ContentProviderOperation.java
+++ b/core/java/android/content/ContentProviderOperation.java
@@ -16,17 +16,22 @@
package android.content;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.UnsupportedAppUsage;
import android.database.Cursor;
import android.net.Uri;
+import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
+import android.util.ArrayMap;
import android.util.Log;
+import android.util.SparseArray;
import java.util.ArrayList;
-import java.util.HashMap;
import java.util.Map;
+import java.util.Objects;
/**
* Represents a single operation to be performed as part of a batch of operations.
@@ -45,20 +50,23 @@
public final static int TYPE_DELETE = 3;
/** @hide exposed for unit tests */
public final static int TYPE_ASSERT = 4;
+ /** @hide exposed for unit tests */
+ public final static int TYPE_CALL = 5;
@UnsupportedAppUsage
private final int mType;
@UnsupportedAppUsage
private final Uri mUri;
+ private final String mMethod;
+ private final String mArg;
+ private final ArrayMap<String, Object> mValues;
+ private final ArrayMap<String, Object> mExtras;
@UnsupportedAppUsage
private final String mSelection;
- private final String[] mSelectionArgs;
- private final ContentValues mValues;
+ private final SparseArray<Object> mSelectionArgs;
private final Integer mExpectedCount;
- private final ContentValues mValuesBackReferences;
- private final Map<Integer, Integer> mSelectionArgsBackReferences;
private final boolean mYieldAllowed;
- private final boolean mFailureAllowed;
+ private final boolean mExceptionAllowed;
private final static String TAG = "ContentProviderOperation";
@@ -69,124 +77,130 @@
private ContentProviderOperation(Builder builder) {
mType = builder.mType;
mUri = builder.mUri;
+ mMethod = builder.mMethod;
+ mArg = builder.mArg;
mValues = builder.mValues;
+ mExtras = builder.mExtras;
mSelection = builder.mSelection;
mSelectionArgs = builder.mSelectionArgs;
mExpectedCount = builder.mExpectedCount;
- mSelectionArgsBackReferences = builder.mSelectionArgsBackReferences;
- mValuesBackReferences = builder.mValuesBackReferences;
mYieldAllowed = builder.mYieldAllowed;
- mFailureAllowed = builder.mFailureAllowed;
+ mExceptionAllowed = builder.mExceptionAllowed;
}
private ContentProviderOperation(Parcel source) {
mType = source.readInt();
mUri = Uri.CREATOR.createFromParcel(source);
- mValues = source.readInt() != 0 ? ContentValues.CREATOR.createFromParcel(source) : null;
- mSelection = source.readInt() != 0 ? source.readString() : null;
- mSelectionArgs = source.readInt() != 0 ? source.readStringArray() : null;
- mExpectedCount = source.readInt() != 0 ? source.readInt() : null;
- mValuesBackReferences = source.readInt() != 0
- ? ContentValues.CREATOR.createFromParcel(source)
- : null;
- mSelectionArgsBackReferences = source.readInt() != 0
- ? new HashMap<Integer, Integer>()
- : null;
- if (mSelectionArgsBackReferences != null) {
- final int count = source.readInt();
- for (int i = 0; i < count; i++) {
- mSelectionArgsBackReferences.put(source.readInt(), source.readInt());
- }
+ mMethod = source.readInt() != 0 ? source.readString() : null;
+ mArg = source.readInt() != 0 ? source.readString() : null;
+ final int valuesSize = source.readInt();
+ if (valuesSize != -1) {
+ mValues = new ArrayMap<>(valuesSize);
+ source.readArrayMap(mValues, null);
+ } else {
+ mValues = null;
}
+ final int extrasSize = source.readInt();
+ if (extrasSize != -1) {
+ mExtras = new ArrayMap<>(extrasSize);
+ source.readArrayMap(mExtras, null);
+ } else {
+ mExtras = null;
+ }
+ mSelection = source.readInt() != 0 ? source.readString() : null;
+ mSelectionArgs = source.readSparseArray(null);
+ mExpectedCount = source.readInt() != 0 ? source.readInt() : null;
mYieldAllowed = source.readInt() != 0;
- mFailureAllowed = source.readInt() != 0;
+ mExceptionAllowed = source.readInt() != 0;
}
/** @hide */
public ContentProviderOperation(ContentProviderOperation cpo, Uri withUri) {
mType = cpo.mType;
mUri = withUri;
+ mMethod = cpo.mMethod;
+ mArg = cpo.mArg;
mValues = cpo.mValues;
+ mExtras = cpo.mExtras;
mSelection = cpo.mSelection;
mSelectionArgs = cpo.mSelectionArgs;
mExpectedCount = cpo.mExpectedCount;
- mSelectionArgsBackReferences = cpo.mSelectionArgsBackReferences;
- mValuesBackReferences = cpo.mValuesBackReferences;
mYieldAllowed = cpo.mYieldAllowed;
- mFailureAllowed = cpo.mFailureAllowed;
+ mExceptionAllowed = cpo.mExceptionAllowed;
}
+ @Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(mType);
Uri.writeToParcel(dest, mUri);
- if (mValues != null) {
+ if (mMethod != null) {
dest.writeInt(1);
- mValues.writeToParcel(dest, 0);
+ dest.writeString(mMethod);
} else {
dest.writeInt(0);
}
+ if (mArg != null) {
+ dest.writeInt(1);
+ dest.writeString(mArg);
+ } else {
+ dest.writeInt(0);
+ }
+ if (mValues != null) {
+ dest.writeInt(mValues.size());
+ dest.writeArrayMap(mValues);
+ } else {
+ dest.writeInt(-1);
+ }
+ if (mExtras != null) {
+ dest.writeInt(mExtras.size());
+ dest.writeArrayMap(mExtras);
+ } else {
+ dest.writeInt(-1);
+ }
if (mSelection != null) {
dest.writeInt(1);
dest.writeString(mSelection);
} else {
dest.writeInt(0);
}
- if (mSelectionArgs != null) {
- dest.writeInt(1);
- dest.writeStringArray(mSelectionArgs);
- } else {
- dest.writeInt(0);
- }
+ dest.writeSparseArray(mSelectionArgs);
if (mExpectedCount != null) {
dest.writeInt(1);
dest.writeInt(mExpectedCount);
} else {
dest.writeInt(0);
}
- if (mValuesBackReferences != null) {
- dest.writeInt(1);
- mValuesBackReferences.writeToParcel(dest, 0);
- } else {
- dest.writeInt(0);
- }
- if (mSelectionArgsBackReferences != null) {
- dest.writeInt(1);
- dest.writeInt(mSelectionArgsBackReferences.size());
- for (Map.Entry<Integer, Integer> entry : mSelectionArgsBackReferences.entrySet()) {
- dest.writeInt(entry.getKey());
- dest.writeInt(entry.getValue());
- }
- } else {
- dest.writeInt(0);
- }
dest.writeInt(mYieldAllowed ? 1 : 0);
- dest.writeInt(mFailureAllowed ? 1 : 0);
+ dest.writeInt(mExceptionAllowed ? 1 : 0);
}
/**
- * Create a {@link Builder} suitable for building an insert {@link ContentProviderOperation}.
- * @param uri The {@link Uri} that is the target of the insert.
- * @return a {@link Builder}
+ * Create a {@link Builder} suitable for building an operation that will
+ * invoke {@link ContentProvider#insert}.
+ *
+ * @param uri The {@link Uri} that is the target of the operation.
*/
- public static Builder newInsert(Uri uri) {
+ public static @NonNull Builder newInsert(@NonNull Uri uri) {
return new Builder(TYPE_INSERT, uri);
}
/**
- * Create a {@link Builder} suitable for building an update {@link ContentProviderOperation}.
- * @param uri The {@link Uri} that is the target of the update.
- * @return a {@link Builder}
+ * Create a {@link Builder} suitable for building an operation that will
+ * invoke {@link ContentProvider#update}.
+ *
+ * @param uri The {@link Uri} that is the target of the operation.
*/
- public static Builder newUpdate(Uri uri) {
+ public static @NonNull Builder newUpdate(@NonNull Uri uri) {
return new Builder(TYPE_UPDATE, uri);
}
/**
- * Create a {@link Builder} suitable for building a delete {@link ContentProviderOperation}.
- * @param uri The {@link Uri} that is the target of the delete.
- * @return a {@link Builder}
+ * Create a {@link Builder} suitable for building an operation that will
+ * invoke {@link ContentProvider#delete}.
+ *
+ * @param uri The {@link Uri} that is the target of the operation.
*/
- public static Builder newDelete(Uri uri) {
+ public static @NonNull Builder newDelete(@NonNull Uri uri) {
return new Builder(TYPE_DELETE, uri);
}
@@ -195,14 +209,25 @@
* {@link ContentProviderOperation} to assert a set of values as provided
* through {@link Builder#withValues(ContentValues)}.
*/
- public static Builder newAssertQuery(Uri uri) {
+ public static @NonNull Builder newAssertQuery(@NonNull Uri uri) {
return new Builder(TYPE_ASSERT, uri);
}
/**
+ * Create a {@link Builder} suitable for building an operation that will
+ * invoke {@link ContentProvider#call}.
+ *
+ * @param uri The {@link Uri} that is the target of the operation.
+ */
+ public static @NonNull Builder newCall(@NonNull Uri uri, @Nullable String method,
+ @Nullable String arg) {
+ return new Builder(TYPE_CALL, uri, method, arg);
+ }
+
+ /**
* Gets the Uri for the target of the operation.
*/
- public Uri getUri() {
+ public @NonNull Uri getUri() {
return mUri;
}
@@ -216,9 +241,13 @@
return mYieldAllowed;
}
- /** {@hide} */
- public boolean isFailureAllowed() {
- return mFailureAllowed;
+ /**
+ * Returns true if this operation allows subsequent operations to continue
+ * even if this operation throws an exception. When true, any encountered
+ * exception is returned via {@link ContentProviderResult#exception}.
+ */
+ public boolean isExceptionAllowed() {
+ return mExceptionAllowed;
}
/** @hide exposed for unit tests */
@@ -228,7 +257,8 @@
}
/**
- * Returns true if the operation represents an insertion.
+ * Returns true if the operation represents a {@link ContentProvider#insert}
+ * operation.
*
* @see #newInsert
*/
@@ -237,7 +267,8 @@
}
/**
- * Returns true if the operation represents a deletion.
+ * Returns true if the operation represents a {@link ContentProvider#delete}
+ * operation.
*
* @see #newDelete
*/
@@ -246,7 +277,8 @@
}
/**
- * Returns true if the operation represents an update.
+ * Returns true if the operation represents a {@link ContentProvider#update}
+ * operation.
*
* @see #newUpdate
*/
@@ -264,6 +296,16 @@
}
/**
+ * Returns true if the operation represents a {@link ContentProvider#call}
+ * operation.
+ *
+ * @see #newCall
+ */
+ public boolean isCall() {
+ return mType == TYPE_CALL;
+ }
+
+ /**
* Returns true if the operation represents an insertion, deletion, or update.
*
* @see #isInsert
@@ -297,13 +339,14 @@
* @throws OperationApplicationException thrown if either the insert fails or
* if the number of rows affected didn't match the expected count
*/
- public ContentProviderResult apply(ContentProvider provider, ContentProviderResult[] backRefs,
- int numBackRefs) throws OperationApplicationException {
- if (mFailureAllowed) {
+ public @NonNull ContentProviderResult apply(@NonNull ContentProvider provider,
+ @NonNull ContentProviderResult[] backRefs, int numBackRefs)
+ throws OperationApplicationException {
+ if (mExceptionAllowed) {
try {
return applyInternal(provider, backRefs, numBackRefs);
} catch (Exception e) {
- return new ContentProviderResult(e.getMessage());
+ return new ContentProviderResult(e);
}
} else {
return applyInternal(provider, backRefs, numBackRefs);
@@ -313,9 +356,9 @@
private ContentProviderResult applyInternal(ContentProvider provider,
ContentProviderResult[] backRefs, int numBackRefs)
throws OperationApplicationException {
- ContentValues values = resolveValueBackReferences(backRefs, numBackRefs);
- String[] selectionArgs =
- resolveSelectionArgsBackReferences(backRefs, numBackRefs);
+ final ContentValues values = resolveValueBackReferences(backRefs, numBackRefs);
+ final Bundle extras = resolveExtrasBackReferences(backRefs, numBackRefs);
+ final String[] selectionArgs = resolveSelectionArgsBackReferences(backRefs, numBackRefs);
if (mType == TYPE_INSERT) {
final Uri newUri = provider.insert(mUri, values);
@@ -325,6 +368,9 @@
throw new OperationApplicationException(
"Insert into " + mUri + " returned no result");
}
+ } else if (mType == TYPE_CALL) {
+ final Bundle res = provider.call(mUri.getAuthority(), mMethod, mArg, extras);
+ return new ContentProviderResult(res);
}
final int numRows;
@@ -376,124 +422,218 @@
}
/**
- * The ContentValues back references are represented as a ContentValues object where the
- * key refers to a column and the value is an index of the back reference whose
- * valued should be associated with the column.
- * <p>
- * This is intended to be a private method but it is exposed for
- * unit testing purposes
- * @param backRefs an array of previous results
- * @param numBackRefs the number of valid previous results in backRefs
- * @return the ContentValues that should be used in this operation application after
- * expansion of back references. This can be called if either mValues or mValuesBackReferences
- * is null
+ * Return the values for this operation after resolving any requested
+ * back-references using the given results.
+ *
+ * @param backRefs the results to use when resolving any back-references
+ * @param numBackRefs the number of results which are valid
*/
- public ContentValues resolveValueBackReferences(
- ContentProviderResult[] backRefs, int numBackRefs) {
- if (mValuesBackReferences == null) {
- return mValues;
- }
- final ContentValues values;
- if (mValues == null) {
- values = new ContentValues();
- } else {
- values = new ContentValues(mValues);
- }
- for (Map.Entry<String, Object> entry : mValuesBackReferences.valueSet()) {
- String key = entry.getKey();
- Integer backRefIndex = mValuesBackReferences.getAsInteger(key);
- if (backRefIndex == null) {
- Log.e(TAG, this.toString());
- throw new IllegalArgumentException("values backref " + key + " is not an integer");
+ public @Nullable ContentValues resolveValueBackReferences(
+ @NonNull ContentProviderResult[] backRefs, int numBackRefs) {
+ if (mValues != null) {
+ final ContentValues values = new ContentValues();
+ for (int i = 0; i < mValues.size(); i++) {
+ final Object value = mValues.valueAt(i);
+ final Object resolved;
+ if (value instanceof BackReference) {
+ resolved = ((BackReference) value).resolve(backRefs, numBackRefs);
+ } else {
+ resolved = value;
+ }
+ values.putObject(mValues.keyAt(i), resolved);
}
- values.put(key, backRefToValue(backRefs, numBackRefs, backRefIndex));
+ return values;
+ } else {
+ return null;
}
- return values;
}
/**
- * The Selection Arguments back references are represented as a Map of Integer->Integer where
- * the key is an index into the selection argument array (see {@link Builder#withSelection})
- * and the value is the index of the previous result that should be used for that selection
- * argument array slot.
- * <p>
- * This is intended to be a private method but it is exposed for
- * unit testing purposes
- * @param backRefs an array of previous results
- * @param numBackRefs the number of valid previous results in backRefs
- * @return the ContentValues that should be used in this operation application after
- * expansion of back references. This can be called if either mValues or mValuesBackReferences
- * is null
+ * Return the extras for this operation after resolving any requested
+ * back-references using the given results.
+ *
+ * @param backRefs the results to use when resolving any back-references
+ * @param numBackRefs the number of results which are valid
*/
- public String[] resolveSelectionArgsBackReferences(
- ContentProviderResult[] backRefs, int numBackRefs) {
- if (mSelectionArgsBackReferences == null) {
- return mSelectionArgs;
+ public @Nullable Bundle resolveExtrasBackReferences(
+ @NonNull ContentProviderResult[] backRefs, int numBackRefs) {
+ if (mExtras != null) {
+ final Bundle extras = new Bundle();
+ for (int i = 0; i < mExtras.size(); i++) {
+ final Object value = mExtras.valueAt(i);
+ final Object resolved;
+ if (value instanceof BackReference) {
+ resolved = ((BackReference) value).resolve(backRefs, numBackRefs);
+ } else {
+ resolved = value;
+ }
+ extras.putObject(mExtras.keyAt(i), resolved);
+ }
+ return extras;
+ } else {
+ return null;
}
- String[] newArgs = new String[mSelectionArgs.length];
- System.arraycopy(mSelectionArgs, 0, newArgs, 0, mSelectionArgs.length);
- for (Map.Entry<Integer, Integer> selectionArgBackRef
- : mSelectionArgsBackReferences.entrySet()) {
- final Integer selectionArgIndex = selectionArgBackRef.getKey();
- final int backRefIndex = selectionArgBackRef.getValue();
- newArgs[selectionArgIndex] =
- String.valueOf(backRefToValue(backRefs, numBackRefs, backRefIndex));
+ }
+
+ /**
+ * Return the selection arguments for this operation after resolving any
+ * requested back-references using the given results.
+ *
+ * @param backRefs the results to use when resolving any back-references
+ * @param numBackRefs the number of results which are valid
+ */
+ public @Nullable String[] resolveSelectionArgsBackReferences(
+ @NonNull ContentProviderResult[] backRefs, int numBackRefs) {
+ if (mSelectionArgs != null) {
+ int max = -1;
+ for (int i = 0; i < mSelectionArgs.size(); i++) {
+ max = Math.max(max, mSelectionArgs.keyAt(i));
+ }
+
+ final String[] selectionArgs = new String[max + 1];
+ for (int i = 0; i < mSelectionArgs.size(); i++) {
+ final Object value = mSelectionArgs.valueAt(i);
+ final Object resolved;
+ if (value instanceof BackReference) {
+ resolved = ((BackReference) value).resolve(backRefs, numBackRefs);
+ } else {
+ resolved = value;
+ }
+ selectionArgs[mSelectionArgs.keyAt(i)] = String.valueOf(resolved);
+ }
+ return selectionArgs;
+ } else {
+ return null;
}
- return newArgs;
+ }
+
+ /** {@hide} */
+ public static String typeToString(int type) {
+ switch (type) {
+ case TYPE_INSERT: return "insert";
+ case TYPE_UPDATE: return "update";
+ case TYPE_DELETE: return "delete";
+ case TYPE_ASSERT: return "assert";
+ case TYPE_CALL: return "call";
+ default: return Integer.toString(type);
+ }
}
@Override
public String toString() {
- return "mType: " + mType + ", mUri: " + mUri +
- ", mSelection: " + mSelection +
- ", mExpectedCount: " + mExpectedCount +
- ", mYieldAllowed: " + mYieldAllowed +
- ", mValues: " + mValues +
- ", mValuesBackReferences: " + mValuesBackReferences +
- ", mSelectionArgsBackReferences: " + mSelectionArgsBackReferences;
+ final StringBuilder sb = new StringBuilder("ContentProviderOperation(");
+ sb.append("type=" + typeToString(mType) + " ");
+ if (mUri != null) {
+ sb.append("uri=" + mUri + " ");
+ }
+ if (mValues != null) {
+ sb.append("values=" + mValues + " ");
+ }
+ if (mSelection != null) {
+ sb.append("selection=" + mSelection + " ");
+ }
+ if (mSelectionArgs != null) {
+ sb.append("selectionArgs=" + mSelectionArgs + " ");
+ }
+ if (mExpectedCount != null) {
+ sb.append("expectedCount=" + mExpectedCount + " ");
+ }
+ if (mYieldAllowed) {
+ sb.append("yieldAllowed ");
+ }
+ if (mExceptionAllowed) {
+ sb.append("exceptionAllowed ");
+ }
+ sb.deleteCharAt(sb.length() - 1);
+ sb.append(")");
+ return sb.toString();
}
- /**
- * Return the string representation of the requested back reference.
- * @param backRefs an array of results
- * @param numBackRefs the number of items in the backRefs array that are valid
- * @param backRefIndex which backRef to be used
- * @throws ArrayIndexOutOfBoundsException thrown if the backRefIndex is larger than
- * the numBackRefs
- * @return the string representation of the requested back reference.
- */
- private long backRefToValue(ContentProviderResult[] backRefs, int numBackRefs,
- Integer backRefIndex) {
- if (backRefIndex >= numBackRefs) {
- Log.e(TAG, this.toString());
- throw new ArrayIndexOutOfBoundsException("asked for back ref " + backRefIndex
- + " but there are only " + numBackRefs + " back refs");
- }
- ContentProviderResult backRef = backRefs[backRefIndex];
- long backRefValue;
- if (backRef.uri != null) {
- backRefValue = ContentUris.parseId(backRef.uri);
- } else {
- backRefValue = backRef.count;
- }
- return backRefValue;
- }
-
+ @Override
public int describeContents() {
return 0;
}
public static final @android.annotation.NonNull Creator<ContentProviderOperation> CREATOR =
new Creator<ContentProviderOperation>() {
+ @Override
public ContentProviderOperation createFromParcel(Parcel source) {
return new ContentProviderOperation(source);
}
+ @Override
public ContentProviderOperation[] newArray(int size) {
return new ContentProviderOperation[size];
}
};
+ /** {@hide} */
+ public static class BackReference implements Parcelable {
+ private final int fromIndex;
+ private final String fromKey;
+
+ private BackReference(int fromIndex, String fromKey) {
+ this.fromIndex = fromIndex;
+ this.fromKey = fromKey;
+ }
+
+ public BackReference(Parcel src) {
+ this.fromIndex = src.readInt();
+ if (src.readInt() != 0) {
+ this.fromKey = src.readString();
+ } else {
+ this.fromKey = null;
+ }
+ }
+
+ public Object resolve(ContentProviderResult[] backRefs, int numBackRefs) {
+ if (fromIndex >= numBackRefs) {
+ Log.e(TAG, this.toString());
+ throw new ArrayIndexOutOfBoundsException("asked for back ref " + fromIndex
+ + " but there are only " + numBackRefs + " back refs");
+ }
+ ContentProviderResult backRef = backRefs[fromIndex];
+ Object backRefValue;
+ if (backRef.extras != null) {
+ backRefValue = backRef.extras.get(fromKey);
+ } else if (backRef.uri != null) {
+ backRefValue = ContentUris.parseId(backRef.uri);
+ } else {
+ backRefValue = (long) backRef.count;
+ }
+ return backRefValue;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(fromIndex);
+ if (fromKey != null) {
+ dest.writeInt(1);
+ dest.writeString(fromKey);
+ } else {
+ dest.writeInt(0);
+ }
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ public static final @android.annotation.NonNull Creator<BackReference> CREATOR =
+ new Creator<BackReference>() {
+ @Override
+ public BackReference createFromParcel(Parcel source) {
+ return new BackReference(source);
+ }
+
+ @Override
+ public BackReference[] newArray(int size) {
+ return new BackReference[size];
+ }
+ };
+ }
+
/**
* Used to add parameters to a {@link ContentProviderOperation}. The {@link Builder} is
* first created by calling {@link ContentProviderOperation#newInsert(android.net.Uri)},
@@ -507,35 +647,36 @@
public static class Builder {
private final int mType;
private final Uri mUri;
+ private final String mMethod;
+ private final String mArg;
+ private ArrayMap<String, Object> mValues;
+ private ArrayMap<String, Object> mExtras;
private String mSelection;
- private String[] mSelectionArgs;
- private ContentValues mValues;
+ private SparseArray<Object> mSelectionArgs;
private Integer mExpectedCount;
- private ContentValues mValuesBackReferences;
- private Map<Integer, Integer> mSelectionArgsBackReferences;
private boolean mYieldAllowed;
- private boolean mFailureAllowed;
+ private boolean mExceptionAllowed;
- /** Create a {@link Builder} of a given type. The uri must not be null. */
private Builder(int type, Uri uri) {
- if (uri == null) {
- throw new IllegalArgumentException("uri must not be null");
- }
+ this(type, uri, null, null);
+ }
+
+ private Builder(int type, Uri uri, String method, String arg) {
mType = type;
- mUri = uri;
+ mUri = Objects.requireNonNull(uri);
+ mMethod = method;
+ mArg = arg;
}
/** Create a ContentProviderOperation from this {@link Builder}. */
- public ContentProviderOperation build() {
+ public @NonNull ContentProviderOperation build() {
if (mType == TYPE_UPDATE) {
- if ((mValues == null || mValues.isEmpty())
- && (mValuesBackReferences == null || mValuesBackReferences.isEmpty())) {
+ if ((mValues == null || mValues.isEmpty())) {
throw new IllegalArgumentException("Empty values");
}
}
if (mType == TYPE_ASSERT) {
if ((mValues == null || mValues.isEmpty())
- && (mValuesBackReferences == null || mValuesBackReferences.isEmpty())
&& (mExpectedCount == null)) {
throw new IllegalArgumentException("Empty values");
}
@@ -543,152 +684,259 @@
return new ContentProviderOperation(this);
}
- /**
- * Add a {@link ContentValues} of back references. The key is the name of the column
- * and the value is an integer that is the index of the previous result whose
- * value should be used for the column. The value is added as a {@link String}.
- * A column value from the back references takes precedence over a value specified in
- * {@link #withValues}.
- * This can only be used with builders of type insert, update, or assert.
- * @return this builder, to allow for chaining.
- */
- public Builder withValueBackReferences(ContentValues backReferences) {
- if (mType != TYPE_INSERT && mType != TYPE_UPDATE && mType != TYPE_ASSERT) {
- throw new IllegalArgumentException(
- "only inserts, updates, and asserts can have value back-references");
- }
- mValuesBackReferences = backReferences;
- return this;
- }
-
- /**
- * Add a ContentValues back reference.
- * A column value from the back references takes precedence over a value specified in
- * {@link #withValues}.
- * This can only be used with builders of type insert, update, or assert.
- * @return this builder, to allow for chaining.
- */
- public Builder withValueBackReference(String key, int previousResult) {
- if (mType != TYPE_INSERT && mType != TYPE_UPDATE && mType != TYPE_ASSERT) {
- throw new IllegalArgumentException(
- "only inserts, updates, and asserts can have value back-references");
- }
- if (mValuesBackReferences == null) {
- mValuesBackReferences = new ContentValues();
- }
- mValuesBackReferences.put(key, previousResult);
- return this;
- }
-
- /**
- * Add a back references as a selection arg. Any value at that index of the selection arg
- * that was specified by {@link #withSelection} will be overwritten.
- * This can only be used with builders of type update, delete, or assert.
- * @return this builder, to allow for chaining.
- */
- public Builder withSelectionBackReference(int selectionArgIndex, int previousResult) {
- if (mType != TYPE_UPDATE && mType != TYPE_DELETE && mType != TYPE_ASSERT) {
- throw new IllegalArgumentException("only updates, deletes, and asserts "
- + "can have selection back-references");
- }
- if (mSelectionArgsBackReferences == null) {
- mSelectionArgsBackReferences = new HashMap<Integer, Integer>();
- }
- mSelectionArgsBackReferences.put(selectionArgIndex, previousResult);
- return this;
- }
-
- /**
- * The ContentValues to use. This may be null. These values may be overwritten by
- * the corresponding value specified by {@link #withValueBackReference} or by
- * future calls to {@link #withValues} or {@link #withValue}.
- * This can only be used with builders of type insert, update, or assert.
- * @return this builder, to allow for chaining.
- */
- public Builder withValues(ContentValues values) {
- if (mType != TYPE_INSERT && mType != TYPE_UPDATE && mType != TYPE_ASSERT) {
- throw new IllegalArgumentException(
- "only inserts, updates, and asserts can have values");
- }
+ private void setValue(@NonNull String key, @NonNull Object value) {
if (mValues == null) {
- mValues = new ContentValues();
+ mValues = new ArrayMap<>();
}
- mValues.putAll(values);
+ final boolean oldReference = mValues.get(key) instanceof BackReference;
+ final boolean newReference = value instanceof BackReference;
+ if (!oldReference || newReference) {
+ mValues.put(key, value);
+ }
+ }
+
+ private void setExtra(@NonNull String key, @NonNull Object value) {
+ if (mExtras == null) {
+ mExtras = new ArrayMap<>();
+ }
+ final boolean oldReference = mExtras.get(key) instanceof BackReference;
+ final boolean newReference = value instanceof BackReference;
+ if (!oldReference || newReference) {
+ mExtras.put(key, value);
+ }
+ }
+
+ private void setSelectionArg(int index, @NonNull Object value) {
+ if (mSelectionArgs == null) {
+ mSelectionArgs = new SparseArray<>();
+ }
+ final boolean oldReference = mSelectionArgs.get(index) instanceof BackReference;
+ final boolean newReference = value instanceof BackReference;
+ if (!oldReference || newReference) {
+ mSelectionArgs.put(index, value);
+ }
+ }
+
+ /**
+ * Configure the values to use for this operation. This method will
+ * replace any previously defined values for the contained keys, but it
+ * will not replace any back-reference requests.
+ * <p>
+ * Any value may be dynamically overwritten using the result of a
+ * previous operation by using methods such as
+ * {@link #withValueBackReference(String, int)}.
+ */
+ public @NonNull Builder withValues(@NonNull ContentValues values) {
+ assertValuesAllowed();
+ final ArrayMap<String, Object> rawValues = values.getValues();
+ for (int i = 0; i < rawValues.size(); i++) {
+ setValue(rawValues.keyAt(i), rawValues.valueAt(i));
+ }
return this;
}
/**
- * A value to insert or update. This value may be overwritten by
- * the corresponding value specified by {@link #withValueBackReference}.
- * This can only be used with builders of type insert, update, or assert.
- * @param key the name of this value
- * @param value the value itself. the type must be acceptable for insertion by
- * {@link ContentValues#put}
- * @return this builder, to allow for chaining.
+ * Configure the given value to use for this operation. This method will
+ * replace any previously defined value for this key.
+ *
+ * @param key the key indicating which value to configure
*/
- public Builder withValue(String key, Object value) {
- if (mType != TYPE_INSERT && mType != TYPE_UPDATE && mType != TYPE_ASSERT) {
- throw new IllegalArgumentException("only inserts and updates can have values");
- }
- if (mValues == null) {
- mValues = new ContentValues();
- }
- if (value == null) {
- mValues.putNull(key);
- } else if (value instanceof String) {
- mValues.put(key, (String) value);
- } else if (value instanceof Byte) {
- mValues.put(key, (Byte) value);
- } else if (value instanceof Short) {
- mValues.put(key, (Short) value);
- } else if (value instanceof Integer) {
- mValues.put(key, (Integer) value);
- } else if (value instanceof Long) {
- mValues.put(key, (Long) value);
- } else if (value instanceof Float) {
- mValues.put(key, (Float) value);
- } else if (value instanceof Double) {
- mValues.put(key, (Double) value);
- } else if (value instanceof Boolean) {
- mValues.put(key, (Boolean) value);
- } else if (value instanceof byte[]) {
- mValues.put(key, (byte[]) value);
- } else {
+ public @NonNull Builder withValue(@NonNull String key, @Nullable Object value) {
+ assertValuesAllowed();
+ if (!ContentValues.isSupportedValue(value)) {
throw new IllegalArgumentException("bad value type: " + value.getClass().getName());
}
+ setValue(key, value);
return this;
}
/**
- * The selection and arguments to use. An occurrence of '?' in the selection will be
- * replaced with the corresponding occurrence of the selection argument. Any of the
- * selection arguments may be overwritten by a selection argument back reference as
- * specified by {@link #withSelectionBackReference}.
- * This can only be used with builders of type update, delete, or assert.
- * @return this builder, to allow for chaining.
+ * Configure the given values to be dynamically overwritten using the
+ * result of a previous operation. This method will replace any
+ * previously defined values for these keys.
+ *
+ * @param backReferences set of values where the key indicates which
+ * value to configure and the value the index indicating
+ * which historical {@link ContentProviderResult} should
+ * overwrite the value
*/
- public Builder withSelection(String selection, String[] selectionArgs) {
- if (mType != TYPE_UPDATE && mType != TYPE_DELETE && mType != TYPE_ASSERT) {
- throw new IllegalArgumentException(
- "only updates, deletes, and asserts can have selections");
+ public @NonNull Builder withValueBackReferences(@NonNull ContentValues backReferences) {
+ assertValuesAllowed();
+ final ArrayMap<String, Object> rawValues = backReferences.getValues();
+ for (int i = 0; i < rawValues.size(); i++) {
+ setValue(rawValues.keyAt(i),
+ new BackReference((int) rawValues.valueAt(i), null));
}
+ return this;
+ }
+
+ /**
+ * Configure the given value to be dynamically overwritten using the
+ * result of a previous operation. This method will replace any
+ * previously defined value for this key.
+ *
+ * @param key the key indicating which value to configure
+ * @param fromIndex the index indicating which historical
+ * {@link ContentProviderResult} should overwrite the value
+ */
+ public @NonNull Builder withValueBackReference(@NonNull String key, int fromIndex) {
+ assertValuesAllowed();
+ setValue(key, new BackReference(fromIndex, null));
+ return this;
+ }
+
+ /**
+ * Configure the given value to be dynamically overwritten using the
+ * result of a previous operation. This method will replace any
+ * previously defined value for this key.
+ *
+ * @param key the key indicating which value to configure
+ * @param fromIndex the index indicating which historical
+ * {@link ContentProviderResult} should overwrite the value
+ * @param fromKey the key of indicating which
+ * {@link ContentProviderResult#extras} value should
+ * overwrite the value
+ */
+ public @NonNull Builder withValueBackReference(@NonNull String key, int fromIndex,
+ @NonNull String fromKey) {
+ assertValuesAllowed();
+ setValue(key, new BackReference(fromIndex, fromKey));
+ return this;
+ }
+
+ /**
+ * Configure the extras to use for this operation. This method will
+ * replace any previously defined values for the contained keys, but it
+ * will not replace any back-reference requests.
+ * <p>
+ * Any value may be dynamically overwritten using the result of a
+ * previous operation by using methods such as
+ * {@link #withExtraBackReference(String, int)}.
+ */
+ public @NonNull Builder withExtras(@NonNull Bundle extras) {
+ assertExtrasAllowed();
+ for (String key : extras.keySet()) {
+ setExtra(key, extras.get(key));
+ }
+ return this;
+ }
+
+ /**
+ * Configure the given extra to use for this operation. This method will
+ * replace any previously defined extras for this key.
+ *
+ * @param key the key indicating which extra to configure
+ */
+ public @NonNull Builder withExtra(@NonNull String key, @Nullable Object value) {
+ assertExtrasAllowed();
+ setExtra(key, value);
+ return this;
+ }
+
+ /**
+ * Configure the given extra to be dynamically overwritten using the
+ * result of a previous operation. This method will replace any
+ * previously defined extras for this key.
+ *
+ * @param key the key indicating which extra to configure
+ * @param fromIndex the index indicating which historical
+ * {@link ContentProviderResult} should overwrite the extra
+ */
+ public @NonNull Builder withExtraBackReference(@NonNull String key, int fromIndex) {
+ assertExtrasAllowed();
+ setExtra(key, new BackReference(fromIndex, null));
+ return this;
+ }
+
+ /**
+ * Configure the given extra to be dynamically overwritten using the
+ * result of a previous operation. This method will replace any
+ * previously defined extras for this key.
+ *
+ * @param key the key indicating which extra to configure
+ * @param fromIndex the index indicating which historical
+ * {@link ContentProviderResult} should overwrite the extra
+ * @param fromKey the key of indicating which
+ * {@link ContentProviderResult#extras} value should
+ * overwrite the extra
+ */
+ public @NonNull Builder withExtraBackReference(@NonNull String key, int fromIndex,
+ @NonNull String fromKey) {
+ assertExtrasAllowed();
+ setExtra(key, new BackReference(fromIndex, fromKey));
+ return this;
+ }
+
+ /**
+ * Configure the selection and selection arguments to use for this
+ * operation. This method will replace any previously defined selection
+ * and selection arguments, but it will not replace any back-reference
+ * requests.
+ * <p>
+ * An occurrence of {@code ?} in the selection will be replaced with the
+ * corresponding selection argument when the operation is executed.
+ * <p>
+ * Any selection argument may be dynamically overwritten using the
+ * result of a previous operation by using methods such as
+ * {@link #withSelectionBackReference(int, int)}.
+ */
+ public @NonNull Builder withSelection(@Nullable String selection,
+ @Nullable String[] selectionArgs) {
+ assertSelectionAllowed();
mSelection = selection;
- if (selectionArgs == null) {
- mSelectionArgs = null;
- } else {
- mSelectionArgs = new String[selectionArgs.length];
- System.arraycopy(selectionArgs, 0, mSelectionArgs, 0, selectionArgs.length);
+ if (selectionArgs != null) {
+ for (int i = 0; i < selectionArgs.length; i++) {
+ setSelectionArg(i, selectionArgs[i]);
+ }
}
return this;
}
/**
+ * Configure the given selection argument to be dynamically overwritten
+ * using the result of a previous operation. This method will replace
+ * any previously defined selection argument at this index.
+ *
+ * @param index the index indicating which selection argument to
+ * configure
+ * @param fromIndex the index indicating which historical
+ * {@link ContentProviderResult} should overwrite the
+ * selection argument
+ */
+ public @NonNull Builder withSelectionBackReference(int index, int fromIndex) {
+ assertSelectionAllowed();
+ setSelectionArg(index, new BackReference(fromIndex, null));
+ return this;
+ }
+
+ /**
+ * Configure the given selection argument to be dynamically overwritten
+ * using the result of a previous operation. This method will replace
+ * any previously defined selection argument at this index.
+ *
+ * @param index the index indicating which selection argument to
+ * configure
+ * @param fromIndex the index indicating which historical
+ * {@link ContentProviderResult} should overwrite the
+ * selection argument
+ * @param fromKey the key of indicating which
+ * {@link ContentProviderResult#extras} value should
+ * overwrite the selection argument
+ */
+ public @NonNull Builder withSelectionBackReference(int index, int fromIndex,
+ @NonNull String fromKey) {
+ assertSelectionAllowed();
+ setSelectionArg(index, new BackReference(fromIndex, fromKey));
+ return this;
+ }
+
+ /**
* If set then if the number of rows affected by this operation does not match
* this count {@link OperationApplicationException} will be throw.
* This can only be used with builders of type update, delete, or assert.
* @return this builder, to allow for chaining.
*/
- public Builder withExpectedCount(int count) {
+ public @NonNull Builder withExpectedCount(int count) {
if (mType != TYPE_UPDATE && mType != TYPE_DELETE && mType != TYPE_ASSERT) {
throw new IllegalArgumentException(
"only updates, deletes, and asserts can have expected counts");
@@ -703,15 +951,59 @@
* @return this builder, to allow for chaining.
* @see android.database.sqlite.SQLiteDatabase#yieldIfContendedSafely()
*/
- public Builder withYieldAllowed(boolean yieldAllowed) {
+ public @NonNull Builder withYieldAllowed(boolean yieldAllowed) {
mYieldAllowed = yieldAllowed;
return this;
}
- /** {@hide} */
- public Builder withFailureAllowed(boolean failureAllowed) {
- mFailureAllowed = failureAllowed;
+ /**
+ * If set to true, this operation allows subsequent operations to
+ * continue even if this operation throws an exception. When true, any
+ * encountered exception is returned via
+ * {@link ContentProviderResult#exception}.
+ */
+ public @NonNull Builder withExceptionAllowed(boolean exceptionAllowed) {
+ mExceptionAllowed = exceptionAllowed;
return this;
}
+
+ /** {@hide} */
+ public @NonNull Builder withFailureAllowed(boolean failureAllowed) {
+ return withExceptionAllowed(failureAllowed);
+ }
+
+ private void assertValuesAllowed() {
+ switch (mType) {
+ case TYPE_INSERT:
+ case TYPE_UPDATE:
+ case TYPE_ASSERT:
+ break;
+ default:
+ throw new IllegalArgumentException(
+ "Values not supported for " + typeToString(mType));
+ }
+ }
+
+ private void assertSelectionAllowed() {
+ switch (mType) {
+ case TYPE_UPDATE:
+ case TYPE_DELETE:
+ case TYPE_ASSERT:
+ break;
+ default:
+ throw new IllegalArgumentException(
+ "Selection not supported for " + typeToString(mType));
+ }
+ }
+
+ private void assertExtrasAllowed() {
+ switch (mType) {
+ case TYPE_CALL:
+ break;
+ default:
+ throw new IllegalArgumentException(
+ "Extras not supported for " + typeToString(mType));
+ }
+ }
}
}
diff --git a/core/java/android/content/ContentProviderResult.java b/core/java/android/content/ContentProviderResult.java
index b301011..11dda83 100644
--- a/core/java/android/content/ContentProviderResult.java
+++ b/core/java/android/content/ContentProviderResult.java
@@ -16,40 +16,50 @@
package android.content;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.net.Uri;
+import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
+import android.os.ParcelableException;
-import com.android.internal.util.Preconditions;
+import java.util.Objects;
/**
- * Contains the result of the application of a {@link ContentProviderOperation}. It is guaranteed
- * to have exactly one of {@link #uri} or {@link #count} set.
+ * Contains the result of the application of a {@link ContentProviderOperation}.
+ * <p>
+ * It is guaranteed to have exactly one of {@link #uri}, {@link #count},
+ * {@link #extras}, or {@link #exception} set.
*/
public class ContentProviderResult implements Parcelable {
- public final Uri uri;
- public final Integer count;
- /** {@hide} */
- public final String failure;
+ public final @Nullable Uri uri;
+ public final @Nullable Integer count;
+ public final @Nullable Bundle extras;
+ public final @Nullable Exception exception;
- public ContentProviderResult(Uri uri) {
- this(Preconditions.checkNotNull(uri), null, null);
+ public ContentProviderResult(@NonNull Uri uri) {
+ this(Objects.requireNonNull(uri), null, null, null);
}
public ContentProviderResult(int count) {
- this(null, count, null);
+ this(null, count, null, null);
+ }
+
+ public ContentProviderResult(@NonNull Bundle extras) {
+ this(null, null, Objects.requireNonNull(extras), null);
+ }
+
+ public ContentProviderResult(@NonNull Exception exception) {
+ this(null, null, null, exception);
}
/** {@hide} */
- public ContentProviderResult(String failure) {
- this(null, null, failure);
- }
-
- /** {@hide} */
- public ContentProviderResult(Uri uri, Integer count, String failure) {
+ public ContentProviderResult(Uri uri, Integer count, Bundle extras, Exception exception) {
this.uri = uri;
this.count = count;
- this.failure = failure;
+ this.extras = extras;
+ this.exception = exception;
}
public ContentProviderResult(Parcel source) {
@@ -64,9 +74,14 @@
count = null;
}
if (source.readInt() != 0) {
- failure = source.readString();
+ extras = source.readBundle();
} else {
- failure = null;
+ extras = null;
+ }
+ if (source.readInt() != 0) {
+ exception = (Exception) ParcelableException.readFromParcel(source);
+ } else {
+ exception = null;
}
}
@@ -74,7 +89,8 @@
public ContentProviderResult(ContentProviderResult cpr, int userId) {
uri = ContentProvider.maybeAddUserId(cpr.uri, userId);
count = cpr.count;
- failure = cpr.failure;
+ extras = cpr.extras;
+ exception = cpr.exception;
}
@Override
@@ -91,9 +107,15 @@
} else {
dest.writeInt(0);
}
- if (failure != null) {
+ if (extras != null) {
dest.writeInt(1);
- dest.writeString(failure);
+ dest.writeBundle(extras);
+ } else {
+ dest.writeInt(0);
+ }
+ if (exception != null) {
+ dest.writeInt(1);
+ ParcelableException.writeToParcel(dest, exception);
} else {
dest.writeInt(0);
}
@@ -126,8 +148,11 @@
if (count != null) {
sb.append("count=" + count + " ");
}
- if (uri != null) {
- sb.append("failure=" + failure + " ");
+ if (extras != null) {
+ sb.append("extras=" + extras + " ");
+ }
+ if (exception != null) {
+ sb.append("exception=" + exception + " ");
}
sb.deleteCharAt(sb.length() - 1);
sb.append(")");
diff --git a/core/java/android/content/ContentValues.java b/core/java/android/content/ContentValues.java
index eafeed2..8223a0b 100644
--- a/core/java/android/content/ContentValues.java
+++ b/core/java/android/content/ContentValues.java
@@ -16,6 +16,8 @@
package android.content;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
@@ -217,6 +219,33 @@
mMap.put(key, null);
}
+ /** {@hide} */
+ public void putObject(@Nullable String key, @Nullable Object value) {
+ if (value == null) {
+ putNull(key);
+ } else if (value instanceof String) {
+ put(key, (String) value);
+ } else if (value instanceof Byte) {
+ put(key, (Byte) value);
+ } else if (value instanceof Short) {
+ put(key, (Short) value);
+ } else if (value instanceof Integer) {
+ put(key, (Integer) value);
+ } else if (value instanceof Long) {
+ put(key, (Long) value);
+ } else if (value instanceof Float) {
+ put(key, (Float) value);
+ } else if (value instanceof Double) {
+ put(key, (Double) value);
+ } else if (value instanceof Boolean) {
+ put(key, (Boolean) value);
+ } else if (value instanceof byte[]) {
+ put(key, (byte[]) value);
+ } else {
+ throw new IllegalArgumentException("Unsupported type " + value.getClass());
+ }
+ }
+
/**
* Returns the number of values.
*
@@ -556,4 +585,31 @@
}
return sb.toString();
}
+
+ /** {@hide} */
+ public static boolean isSupportedValue(Object value) {
+ if (value == null) {
+ return true;
+ } else if (value instanceof String) {
+ return true;
+ } else if (value instanceof Byte) {
+ return true;
+ } else if (value instanceof Short) {
+ return true;
+ } else if (value instanceof Integer) {
+ return true;
+ } else if (value instanceof Long) {
+ return true;
+ } else if (value instanceof Float) {
+ return true;
+ } else if (value instanceof Double) {
+ return true;
+ } else if (value instanceof Boolean) {
+ return true;
+ } else if (value instanceof byte[]) {
+ return true;
+ } else {
+ return false;
+ }
+ }
}
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index a4933ef..ef08bf5 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -621,21 +621,6 @@
}
/**
- * Generate and return the {@link PackageInfo} for a parsed package.
- *
- * @param p the parsed package.
- * @param flags indicating which optional information is included.
- */
- @UnsupportedAppUsage
- public static PackageInfo generatePackageInfo(PackageParser.Package p,
- int gids[], int flags, long firstInstallTime, long lastUpdateTime,
- Set<String> grantedPermissions, PackageUserState state) {
-
- return generatePackageInfo(p, gids, flags, firstInstallTime, lastUpdateTime,
- grantedPermissions, state, UserHandle.getCallingUserId());
- }
-
- /**
* Returns true if the package is installed and not hidden, or if the caller
* explicitly wanted all uninstalled and hidden packages as well.
* @param appInfo The applicationInfo of the app being checked.
@@ -661,8 +646,45 @@
return checkUseInstalledOrHidden(0, state, null);
}
+ /**
+ * Generate and return the {@link PackageInfo} for a parsed package.
+ *
+ * @param p the parsed package.
+ * @param flags indicating which optional information is included.
+ */
@UnsupportedAppUsage
public static PackageInfo generatePackageInfo(PackageParser.Package p,
+ int[] gids, int flags, long firstInstallTime, long lastUpdateTime,
+ Set<String> grantedPermissions, PackageUserState state) {
+
+ return generatePackageInfo(p, gids, flags, firstInstallTime, lastUpdateTime,
+ grantedPermissions, state, UserHandle.getCallingUserId());
+ }
+
+ @UnsupportedAppUsage
+ public static PackageInfo generatePackageInfo(PackageParser.Package p,
+ int[] gids, int flags, long firstInstallTime, long lastUpdateTime,
+ Set<String> grantedPermissions, PackageUserState state, int userId) {
+
+ return generatePackageInfo(p, null, gids, flags, firstInstallTime, lastUpdateTime,
+ grantedPermissions, state, userId);
+ }
+
+ /**
+ * PackageInfo generator specifically for apex files.
+ *
+ * @param pkg Package to generate info from. Should be derived from an apex.
+ * @param apexInfo Apex info relating to the package.
+ * @return PackageInfo
+ * @throws PackageParserException
+ */
+ public static PackageInfo generatePackageInfo(
+ PackageParser.Package pkg, ApexInfo apexInfo, int flags) {
+ return generatePackageInfo(pkg, apexInfo, EmptyArray.INT, flags, 0, 0,
+ Collections.emptySet(), new PackageUserState(), UserHandle.getCallingUserId());
+ }
+
+ private static PackageInfo generatePackageInfo(PackageParser.Package p, ApexInfo apexInfo,
int gids[], int flags, long firstInstallTime, long lastUpdateTime,
Set<String> grantedPermissions, PackageUserState state, int userId) {
if (!checkUseInstalledOrHidden(flags, state, p.applicationInfo) || !p.isMatch(flags)) {
@@ -809,8 +831,27 @@
}
}
}
+
+ if (apexInfo != null) {
+ File apexFile = new File(apexInfo.modulePath);
+
+ pi.applicationInfo.sourceDir = apexFile.getPath();
+ pi.applicationInfo.publicSourceDir = apexFile.getPath();
+ if (apexInfo.isFactory) {
+ pi.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
+ } else {
+ pi.applicationInfo.flags &= ~ApplicationInfo.FLAG_SYSTEM;
+ }
+ if (apexInfo.isActive) {
+ pi.applicationInfo.flags |= ApplicationInfo.FLAG_INSTALLED;
+ } else {
+ pi.applicationInfo.flags &= ~ApplicationInfo.FLAG_INSTALLED;
+ }
+ pi.isApex = true;
+ }
+
// deprecated method of getting signing certificates
- if ((flags&PackageManager.GET_SIGNATURES) != 0) {
+ if ((flags & PackageManager.GET_SIGNATURES) != 0) {
if (p.mSigningDetails.hasPastSigningCertificates()) {
// Package has included signing certificate rotation information. Return the oldest
// cert so that programmatic checks keep working even if unaware of key rotation.
@@ -8461,61 +8502,4 @@
}
}
- // TODO(b/129261524): Clean up API
- /**
- * PackageInfo parser specifically for apex files.
- * NOTE: It will collect certificates
- *
- * @param apexInfo
- * @return PackageInfo
- * @throws PackageParserException
- */
- public static PackageInfo generatePackageInfoFromApex(ApexInfo apexInfo, int flags)
- throws PackageParserException {
- PackageParser pp = new PackageParser();
- File apexFile = new File(apexInfo.modulePath);
- final Package p = pp.parsePackage(apexFile, flags, false);
- PackageUserState state = new PackageUserState();
- PackageInfo pi = generatePackageInfo(p, EmptyArray.INT, flags, 0, 0,
- Collections.emptySet(), state);
- pi.applicationInfo.sourceDir = apexFile.getPath();
- pi.applicationInfo.publicSourceDir = apexFile.getPath();
- if (apexInfo.isFactory) {
- pi.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
- } else {
- pi.applicationInfo.flags &= ~ApplicationInfo.FLAG_SYSTEM;
- }
- if (apexInfo.isActive) {
- pi.applicationInfo.flags |= ApplicationInfo.FLAG_INSTALLED;
- } else {
- pi.applicationInfo.flags &= ~ApplicationInfo.FLAG_INSTALLED;
- }
- pi.isApex = true;
-
- // Collect certificates
- if ((flags & PackageManager.GET_SIGNING_CERTIFICATES) != 0) {
- collectCertificates(p, apexFile, false);
- // Keep legacy mechanism for handling signatures. While this is deprecated, it's
- // still part of the public API and needs to be maintained
- if (p.mSigningDetails.hasPastSigningCertificates()) {
- // Package has included signing certificate rotation information. Return
- // the oldest cert so that programmatic checks keep working even if unaware
- // of key rotation.
- pi.signatures = new Signature[1];
- pi.signatures[0] = p.mSigningDetails.pastSigningCertificates[0];
- } else if (p.mSigningDetails.hasSignatures()) {
- // otherwise keep old behavior
- int numberOfSigs = p.mSigningDetails.signatures.length;
- pi.signatures = new Signature[numberOfSigs];
- System.arraycopy(p.mSigningDetails.signatures, 0, pi.signatures, 0, numberOfSigs);
- }
- if (p.mSigningDetails != SigningDetails.UNKNOWN) {
- // only return a valid SigningInfo if there is signing information to report
- pi.signingInfo = new SigningInfo(p.mSigningDetails);
- } else {
- pi.signingInfo = null;
- }
- }
- return pi;
- }
}
diff --git a/core/java/android/content/pm/UserInfo.java b/core/java/android/content/pm/UserInfo.java
index 7865d75..1c37c64 100644
--- a/core/java/android/content/pm/UserInfo.java
+++ b/core/java/android/content/pm/UserInfo.java
@@ -24,6 +24,18 @@
/**
* Per-user information.
+ *
+ * <p>There are 3 base properties of users: {@link #FLAG_SYSTEM}, {@link #FLAG_FULL}, and
+ * {@link #FLAG_MANAGED_PROFILE}. Every user must have one of the following combination of these
+ * flags:
+ * <ul>
+ * <li>FLAG_SYSTEM (user {@link UserHandle#USER_SYSTEM} on a headless-user-0 device)</li>
+ * <li>FLAG_SYSTEM and FLAG_FULL (user {@link UserHandle#USER_SYSTEM} on a regular device)</li>
+ * <li>FLAG_FULL (non-profile secondary user)</li>
+ * <li>FLAG_MANAGED_PROFILE (profile users)</li>
+ * </ul>
+ * Users can have also have additional flags (such as FLAG_GUEST) as appropriate.
+ *
* @hide
*/
public class UserInfo implements Parcelable {
@@ -93,6 +105,20 @@
*/
public static final int FLAG_DEMO = 0x00000200;
+ /**
+ * Indicates that this user is a non-profile human user.
+ *
+ * <p>When creating a new (non-system) user, this flag will always be forced true unless the
+ * user is a {@link #FLAG_MANAGED_PROFILE}. If user {@link UserHandle#USER_SYSTEM} is also a
+ * human user, it must also be flagged as FULL.
+ */
+ public static final int FLAG_FULL = 0x00000400;
+
+ /**
+ * Indicates that this user is {@link UserHandle#USER_SYSTEM}. Not applicable to created users.
+ */
+ public static final int FLAG_SYSTEM = 0x00000800;
+
public static final int NO_PROFILE_GROUP_ID = UserHandle.USER_NULL;
@UnsupportedAppUsage
diff --git a/core/java/android/hardware/radio/TunerAdapter.java b/core/java/android/hardware/radio/TunerAdapter.java
index be2846f..aa5480a 100644
--- a/core/java/android/hardware/radio/TunerAdapter.java
+++ b/core/java/android/hardware/radio/TunerAdapter.java
@@ -271,6 +271,8 @@
mCallback.setProgramListObserver(list, () -> {
try {
mTuner.stopProgramListUpdates();
+ } catch (IllegalStateException ex) {
+ // it's fine to not stop updates if tuner is already closed
} catch (RemoteException ex) {
Log.e(TAG, "Couldn't stop program list updates", ex);
}
diff --git a/core/java/android/os/BaseBundle.java b/core/java/android/os/BaseBundle.java
index 7f63f8f..9d9c683 100644
--- a/core/java/android/os/BaseBundle.java
+++ b/core/java/android/os/BaseBundle.java
@@ -563,6 +563,35 @@
return mMap.keySet();
}
+ /** {@hide} */
+ public void putObject(@Nullable String key, @Nullable Object value) {
+ if (value == null) {
+ putString(key, null);
+ } else if (value instanceof Boolean) {
+ putBoolean(key, (Boolean) value);
+ } else if (value instanceof Integer) {
+ putInt(key, (Integer) value);
+ } else if (value instanceof Long) {
+ putLong(key, (Long) value);
+ } else if (value instanceof Double) {
+ putDouble(key, (Double) value);
+ } else if (value instanceof String) {
+ putString(key, (String) value);
+ } else if (value instanceof boolean[]) {
+ putBooleanArray(key, (boolean[]) value);
+ } else if (value instanceof int[]) {
+ putIntArray(key, (int[]) value);
+ } else if (value instanceof long[]) {
+ putLongArray(key, (long[]) value);
+ } else if (value instanceof double[]) {
+ putDoubleArray(key, (double[]) value);
+ } else if (value instanceof String[]) {
+ putStringArray(key, (String[]) value);
+ } else {
+ throw new IllegalArgumentException("Unsupported type " + value.getClass());
+ }
+ }
+
/**
* Inserts a Boolean value into the mapping of this Bundle, replacing
* any existing value for the given key. Either key or value may be null.
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index a399e83..c5c0945 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -21,7 +21,6 @@
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,6 +44,7 @@
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;
@@ -56,6 +56,7 @@
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
@@ -407,6 +408,40 @@
};
/**
+ * "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 {
@@ -4260,17 +4295,18 @@
}
}
+ final Object[] jobCompletionArgs = new Object[sJobStopReasonCodes.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) {
- dumpLine(pw, uid, category, JOB_COMPLETION_DATA,
- "\"" + completions.keyAt(ic) + "\"",
- types.get(JobParameters.REASON_CANCELED, 0),
- types.get(JobParameters.REASON_CONSTRAINTS_NOT_SATISFIED, 0),
- types.get(JobParameters.REASON_PREEMPT, 0),
- types.get(JobParameters.REASON_TIMEOUT, 0),
- types.get(JobParameters.REASON_DEVICE_IDLE, 0));
+ jobCompletionArgs[0] = "\"" + completions.keyAt(ic) + "\"";
+ for (int i = 0; i < sJobStopReasonCodes.length; i++) {
+ jobCompletionArgs[i + 1] = types.get(sJobStopReasonCodes[i], 0);
+ }
+
+ dumpLine(pw, uid, category, JOB_COMPLETION_DATA, jobCompletionArgs);
}
}
@@ -5887,7 +5923,7 @@
pw.print(":");
for (int it=0; it<types.size(); it++) {
pw.print(" ");
- pw.print(JobParameters.getReasonName(types.keyAt(it)));
+ pw.print(sJobStopReasonNameConverter.apply(types.keyAt(it)));
pw.print("(");
pw.print(types.valueAt(it));
pw.print("x)");
@@ -7478,13 +7514,6 @@
// Job completion (JOB_COMPLETION_DATA)
final ArrayMap<String, SparseIntArray> completions = u.getJobCompletionStats();
- final int[] reasons = new int[]{
- JobParameters.REASON_CANCELED,
- JobParameters.REASON_CONSTRAINTS_NOT_SATISFIED,
- JobParameters.REASON_PREEMPT,
- JobParameters.REASON_TIMEOUT,
- JobParameters.REASON_DEVICE_IDLE,
- };
for (int ic = 0; ic < completions.size(); ++ic) {
SparseIntArray types = completions.valueAt(ic);
if (types != null) {
@@ -7492,7 +7521,7 @@
proto.write(UidProto.JobCompletion.NAME, completions.keyAt(ic));
- for (int r : reasons) {
+ for (int r : sJobStopReasonCodes) {
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/Bundle.java b/core/java/android/os/Bundle.java
index b82e517..7e11840 100644
--- a/core/java/android/os/Bundle.java
+++ b/core/java/android/os/Bundle.java
@@ -435,6 +435,56 @@
return bundle;
}
+ /** {@hide} */
+ @Override
+ public void putObject(@Nullable String key, @Nullable Object value) {
+ if (value instanceof Byte) {
+ putByte(key, (Byte) value);
+ } else if (value instanceof Character) {
+ putChar(key, (Character) value);
+ } else if (value instanceof Short) {
+ putShort(key, (Short) value);
+ } else if (value instanceof Float) {
+ putFloat(key, (Float) value);
+ } else if (value instanceof CharSequence) {
+ putCharSequence(key, (CharSequence) value);
+ } else if (value instanceof Parcelable) {
+ putParcelable(key, (Parcelable) value);
+ } else if (value instanceof Size) {
+ putSize(key, (Size) value);
+ } else if (value instanceof SizeF) {
+ putSizeF(key, (SizeF) value);
+ } else if (value instanceof Parcelable[]) {
+ putParcelableArray(key, (Parcelable[]) value);
+ } else if (value instanceof ArrayList) {
+ putParcelableArrayList(key, (ArrayList) value);
+ } else if (value instanceof List) {
+ putParcelableList(key, (List) value);
+ } else if (value instanceof SparseArray) {
+ putSparseParcelableArray(key, (SparseArray) value);
+ } else if (value instanceof Serializable) {
+ putSerializable(key, (Serializable) value);
+ } else if (value instanceof byte[]) {
+ putByteArray(key, (byte[]) value);
+ } else if (value instanceof short[]) {
+ putShortArray(key, (short[]) value);
+ } else if (value instanceof char[]) {
+ putCharArray(key, (char[]) value);
+ } else if (value instanceof float[]) {
+ putFloatArray(key, (float[]) value);
+ } else if (value instanceof CharSequence[]) {
+ putCharSequenceArray(key, (CharSequence[]) value);
+ } else if (value instanceof Bundle) {
+ putBundle(key, (Bundle) value);
+ } else if (value instanceof Binder) {
+ putBinder(key, (Binder) value);
+ } else if (value instanceof IBinder) {
+ putIBinder(key, (IBinder) value);
+ } else {
+ super.putObject(key, value);
+ }
+ }
+
/**
* Inserts a byte value into the mapping of this Bundle, replacing
* any existing value for the given key.
diff --git a/core/java/android/os/Debug.java b/core/java/android/os/Debug.java
index 1213eea..3cc2819 100644
--- a/core/java/android/os/Debug.java
+++ b/core/java/android/os/Debug.java
@@ -787,6 +787,68 @@
}
/**
+ * Rss of Java Heap bytes in KB due to the application.
+ * @hide
+ */
+ public int getSummaryJavaHeapRss() {
+ return dalvikRss + getOtherRss(OTHER_ART);
+ }
+
+ /**
+ * Rss of Native Heap bytes in KB due to the application.
+ * @hide
+ */
+ public int getSummaryNativeHeapRss() {
+ return nativeRss;
+ }
+
+ /**
+ * Rss of code and other static resource bytes in KB due to
+ * the application.
+ * @hide
+ */
+ public int getSummaryCodeRss() {
+ return getOtherRss(OTHER_SO)
+ + getOtherRss(OTHER_JAR)
+ + getOtherRss(OTHER_APK)
+ + getOtherRss(OTHER_TTF)
+ + getOtherRss(OTHER_DEX)
+ + getOtherRss(OTHER_OAT);
+ }
+
+ /**
+ * Rss in KB of the stack due to the application.
+ * @hide
+ */
+ public int getSummaryStackRss() {
+ return getOtherRss(OTHER_STACK);
+ }
+
+ /**
+ * Rss in KB of graphics due to the application.
+ * @hide
+ */
+ public int getSummaryGraphicsRss() {
+ return getOtherRss(OTHER_GL_DEV)
+ + getOtherRss(OTHER_GRAPHICS)
+ + getOtherRss(OTHER_GL);
+ }
+
+ /**
+ * Rss in KB due to either the application or system that haven't otherwise been
+ * accounted for.
+ * @hide
+ */
+ public int getSummaryUnknownRss() {
+ return getTotalRss()
+ - getSummaryJavaHeapRss()
+ - getSummaryNativeHeapRss()
+ - getSummaryCodeRss()
+ - getSummaryStackRss()
+ - getSummaryGraphicsRss();
+ }
+
+ /**
* Total Pss in KB.
* @hide
*/
diff --git a/core/java/android/os/ZygoteProcess.java b/core/java/android/os/ZygoteProcess.java
index cdd0d45..eaf9929 100644
--- a/core/java/android/os/ZygoteProcess.java
+++ b/core/java/android/os/ZygoteProcess.java
@@ -738,6 +738,31 @@
}
/**
+ * Notify the Zygote processes that boot completed.
+ */
+ public void bootCompleted() {
+ // Notify both the 32-bit and 64-bit zygote.
+ if (Build.SUPPORTED_32_BIT_ABIS.length > 0) {
+ bootCompleted(Build.SUPPORTED_32_BIT_ABIS[0]);
+ }
+ if (Build.SUPPORTED_64_BIT_ABIS.length > 0) {
+ bootCompleted(Build.SUPPORTED_64_BIT_ABIS[0]);
+ }
+ }
+
+ private void bootCompleted(String abi) {
+ try {
+ synchronized (mLock) {
+ ZygoteState state = openZygoteSocketIfNeeded(abi);
+ state.mZygoteOutputWriter.write("1\n--boot-completed\n");
+ state.mZygoteOutputWriter.flush();
+ }
+ } catch (Exception ex) {
+ throw new RuntimeException("Failed to inform zygote of boot_completed", ex);
+ }
+ }
+
+ /**
* Push hidden API blacklisting exemptions into the zygote process(es).
*
* <p>The list of exemptions will take affect for all new processes forked from the zygote after
diff --git a/core/java/android/os/image/DynamicSystemManager.java b/core/java/android/os/image/DynamicSystemManager.java
index cec1945..e4f88c5 100644
--- a/core/java/android/os/image/DynamicSystemManager.java
+++ b/core/java/android/os/image/DynamicSystemManager.java
@@ -76,7 +76,7 @@
@RequiresPermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM)
public boolean commit() {
try {
- return mService.commit();
+ return mService.setEnable(true, true);
} catch (RemoteException e) {
throw new RuntimeException(e.toString());
}
@@ -188,9 +188,9 @@
* @return {@code true} if the call succeeds. {@code false} if there is no installed image.
*/
@RequiresPermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM)
- public boolean setEnable(boolean enable) {
+ public boolean setEnable(boolean enable, boolean oneShot) {
try {
- return mService.setEnable(enable);
+ return mService.setEnable(enable, oneShot);
} catch (RemoteException e) {
throw new RuntimeException(e.toString());
}
diff --git a/core/java/android/os/image/IDynamicSystemService.aidl b/core/java/android/os/image/IDynamicSystemService.aidl
index a34daca..2f4ab2d 100644
--- a/core/java/android/os/image/IDynamicSystemService.aidl
+++ b/core/java/android/os/image/IDynamicSystemService.aidl
@@ -72,9 +72,11 @@
/**
* Enable or disable DynamicSystem.
*
+ * @param oneShot If true, the GSI will boot once and then disable itself.
+ *
* @return true if the call succeeds
*/
- boolean setEnable(boolean enable);
+ boolean setEnable(boolean enable, boolean oneShot);
/**
* Write a chunk of the DynamicSystem system image
@@ -83,10 +85,4 @@
*/
boolean write(in byte[] buf);
- /**
- * Finish write and make device to boot into the it after reboot.
- *
- * @return true if the call succeeds
- */
- boolean commit();
}
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index 81e1eb9..af3a16c 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -870,8 +870,8 @@
protected interface ContactOptionsColumns {
/**
* The number of times a contact has been contacted.
- * <p class="caution"><b>Caution: </b>As of January 7, 2019, this field is obsolete. For
- * more information, see the
+ * <p class="caution"><b>Caution: </b>If you publish your app to the Google Play Store,
+ * this field is obsolete, regardless of Android version. For more information, see the
* <a href="/guide/topics/providers/contacts-provider#ObsoleteData">Contacts Provider</a>
* page.</p>
* <P>Type: INTEGER</P>
@@ -885,8 +885,8 @@
/**
* The last time a contact was contacted.
- * <p class="caution"><b>Caution: </b>As of January 7, 2019, this field is obsolete. For
- * more information, see the
+ * <p class="caution"><b>Caution: </b>If you publish your app to the Google Play Store,
+ * this field is obsolete, regardless of Android version. For more information, see the
* <a href="/guide/topics/providers/contacts-provider#ObsoleteData">Contacts Provider</a>
* page.</p>
* <P>Type: INTEGER</P>
@@ -1691,10 +1691,10 @@
* TIMES_CONTACTED field is incremented by 1 and the LAST_TIME_CONTACTED
* field is populated with the current system time.
*
- * <p class="caution"><b>Caution: </b>As of January 7, 2019, this method is obsolete. For
- * more information, see the
+ * <p class="caution"><b>Caution: </b>If you publish your app to the Google Play Store,
+ * this field is obsolete, regardless of Android version. For more information, see the
* <a href="/guide/topics/providers/contacts-provider#ObsoleteData">Contacts Provider</a>
- * page.
+ * page.</p>
*
* @param resolver the ContentResolver to use
* @param contactId the person who was contacted
@@ -1730,8 +1730,8 @@
* Frequent contacts are no longer included in the result as of
* Android version {@link android.os.Build.VERSION_CODES#Q}.
*
- * <p class="caution"><b>Caution: </b>As of January 7, 2019, this field no longer sorts
- * results based on contacts frequency. For more information, see the
+ * <p class="caution"><b>Caution: </b>If you publish your app to the Google Play Store, this
+ * field doesn't sort results based on contacts frequency. For more information, see the
* <a href="/guide/topics/providers/contacts-provider#ObsoleteData">Contacts Provider</a>
* page.
*/
@@ -1745,8 +1745,8 @@
* Android version {@link android.os.Build.VERSION_CODES#Q}.
* This URI always returns an empty cursor.
*
- * <p class="caution"><b>Caution: </b>As of January 7, 2019, this field no longer sorts
- * results based on contacts frequency. For more information, see the
+ * <p class="caution"><b>Caution: </b>If you publish your app to the Google Play Store, this
+ * field doesn't sort results based on contacts frequency. For more information, see the
* <a href="/guide/topics/providers/contacts-provider#ObsoleteData">Contacts Provider</a>
* page.
*/
@@ -1760,8 +1760,8 @@
* various parts of the contact name. The filter argument should be passed
* as an additional path segment after this URI.
*
- * <p class="caution"><b>Caution: </b>As of January 7, 2019, this field no longer sorts
- * results based on contacts frequency. For more information, see the
+ * <p class="caution"><b>Caution: </b>If you publish your app to the Google Play Store, this
+ * field doesn't sort results based on contacts frequency. For more information, see the
* <a href="/guide/topics/providers/contacts-provider#ObsoleteData">Contacts Provider</a>
* page.
*/
@@ -4292,10 +4292,10 @@
* Android version {@link android.os.Build.VERSION_CODES#Q}.
* This column always contains 0.
*
- * <p class="caution"><b>Caution: </b>As of January 7, 2019, this field is obsolete.
- * For more information, see the
+ * <p class="caution"><b>Caution: </b>If you publish your app to the Google Play Store,
+ * this field is obsolete, regardless of Android version. For more information, see the
* <a href="/guide/topics/providers/contacts-provider#ObsoleteData">Contacts Provider</a>
- * page.
+ * page.</p>
*/
@Deprecated
public static final String LAST_TIME_USED = "last_time_used";
@@ -4306,10 +4306,10 @@
* Android version {@link android.os.Build.VERSION_CODES#Q}.
* This column always contains 0.
*
- * <p class="caution"><b>Caution: </b>As of January 7, 2019, this field is obsolete.
- * For more information, see the
+ * <p class="caution"><b>Caution: </b>If you publish your app to the Google Play Store,
+ * this field is obsolete, regardless of Android version. For more information, see the
* <a href="/guide/topics/providers/contacts-provider#ObsoleteData">Contacts Provider</a>
- * page.
+ * page.</p>
*/
@Deprecated
public static final String TIMES_USED = "times_used";
@@ -5259,8 +5259,8 @@
/**
* The content:// style URI for this table.
*
- * <p class="caution"><b>Caution: </b>As of January 7, 2019, this field no longer
- * sorts results based on contacts frequency. For more information, see the
+ * <p class="caution"><b>Caution: </b>If you publish your app to the Google Play Store, this
+ * field doesn't sort results based on contacts frequency. For more information, see the
* <a href="/guide/topics/providers/contacts-provider#ObsoleteData">Contacts Provider</a>
* page.
*
@@ -5277,8 +5277,8 @@
/**
* <p>URI used for the "enterprise caller-id".</p>
*
- * <p class="caution"><b>Caution: </b>As of January 7, 2019, this field no longer
- * sorts results based on contacts frequency. For more information, see the
+ * <p class="caution"><b>Caution: </b>If you publish your app to the Google Play Store, this
+ * field doesn't sort results based on contacts frequency. For more information, see the
* <a href="/guide/topics/providers/contacts-provider#ObsoleteData">Contacts Provider</a>
* page.
*
@@ -6079,8 +6079,8 @@
* to display names as well as phone numbers. The filter argument should be passed
* as an additional path segment after this URI.
*
- * <p class="caution"><b>Caution: </b>As of January 7, 2019, this field no longer
- * sorts results based on contacts frequency. For more information, see the
+ * <p class="caution"><b>Caution: </b>This field deosn't sort results based on contacts
+ * frequency. For more information, see the
* <a href="/guide/topics/providers/contacts-provider#ObsoleteData">Contacts Provider</a>
* page.
*/
@@ -6092,8 +6092,9 @@
* same columns. This URI requires {@link ContactsContract#DIRECTORY_PARAM_KEY} in
* parameters, otherwise it will throw IllegalArgumentException.
*
- * <p class="caution"><b>Caution: </b>As of January 7, 2019, this field no longer sorts
- * results based on contacts frequency. For more information, see the
+ * <p class="caution"><b>Caution: </b>If you publish your app to the Google Play Store,
+ * this field doesn't sort results based on contacts frequency. For more information,
+ * see the
* <a href="/guide/topics/providers/contacts-provider#ObsoleteData">Contacts Provider</a>
* page.
*/
@@ -6360,8 +6361,9 @@
* as an additional path segment after this URI.
* </p>
*
- * <p class="caution"><b>Caution: </b>As of January 7, 2019, this field no longer sorts
- * results based on contacts frequency. For more information, see the
+ * <p class="caution"><b>Caution: </b>If you publish your app to the Google Play Store,
+ * this field doesn't sort results based on contacts frequency. For more information,
+ * see the
* <a href="/guide/topics/providers/contacts-provider#ObsoleteData">Contacts Provider</a>
* page.</p>
*
@@ -6383,8 +6385,9 @@
* same columns. This URI requires {@link ContactsContract#DIRECTORY_PARAM_KEY} in
* parameters, otherwise it will throw IllegalArgumentException.
*
- * <p class="caution"><b>Caution: </b>As of January 7, 2019, this field no longer
- * sorts results based on contacts frequency. For more information, see the
+ * <p class="caution"><b>Caution: </b>If you publish your app to the Google Play Store,
+ * this field doesn't sort results based on contacts frequency. For more information,
+ * see the
* <a href="/guide/topics/providers/contacts-provider#ObsoleteData">Contacts Provider</a>
* page.
*/
@@ -7602,8 +7605,8 @@
* <p>Similar to {@link Phone#CONTENT_FILTER_URI}, but allows users to filter callable
* data.
*
- * <p class="caution"><b>Caution: </b>As of January 7, 2019, this field no longer
- * sorts results based on contacts frequency. For more information, see the
+ * <p class="caution"><b>Caution: </b>This field no longer sorts results based on
+ * contacts frequency. For more information, see the
* <a href="/guide/topics/providers/contacts-provider#ObsoleteData">Contacts Provider</a>
* page.
*/
@@ -7615,8 +7618,9 @@
* callable data. This URI requires {@link ContactsContract#DIRECTORY_PARAM_KEY} in
* parameters, otherwise it will throw IllegalArgumentException.
*
- * <p class="caution"><b>Caution: </b>As of January 7, 2019, this field no longer
- * sorts results based on contacts frequency. For more information, see the
+ * <p class="caution"><b>Caution: </b>If you publish your app to the Google Play Store,
+ * this field doesn't sort results based on contacts frequency. For more information,
+ * see the
* <a href="/guide/topics/providers/contacts-provider#ObsoleteData">Contacts Provider</a>
* page.</p>
*/
@@ -7646,8 +7650,9 @@
* <p>The content:// style URI for these data items, which allows for a query parameter
* to be appended onto the end to filter for data items matching the query.
*
- * <p class="caution"><b>Caution: </b>As of January 7, 2019, this field no longer
- * sorts results based on contacts frequency. For more information, see the
+ * <p class="caution"><b>Caution: </b>If you publish your app to the Google Play Store,
+ * this field doesn't sort results based on contacts frequency. For more information,
+ * see the
* <a href="/guide/topics/providers/contacts-provider#ObsoleteData">Contacts Provider</a>
* page.
*/
@@ -8298,15 +8303,14 @@
}
/**
- * <p class="caution"><b>Caution: </b>As of January 7, 2019, this class is obsolete. For
- * more information, see the
- * <a href="/guide/topics/providers/contacts-provider#ObsoleteData">Contacts Provider</a>
- * page.
- * </p>
* <p>
* API allowing applications to send usage information for each {@link Data} row to the
* Contacts Provider. Applications can also clear all usage information.
* </p>
+ * <p class="caution"><b>Caution: </b>If you publish your app to the Google Play Store,
+ * this field is obsolete, regardless of Android version. For more information, see the
+ * <a href="/guide/topics/providers/contacts-provider#ObsoleteData">Contacts Provider</a>
+ * page.</p>
* <p>
* With the feedback, Contacts Provider may return more contextually appropriate results for
* Data listing, typically supplied with
diff --git a/core/java/android/provider/MediaStore.java b/core/java/android/provider/MediaStore.java
index 2a590ce..2299aad 100644
--- a/core/java/android/provider/MediaStore.java
+++ b/core/java/android/provider/MediaStore.java
@@ -137,6 +137,8 @@
public static final String VOLUME_EXTERNAL_PRIMARY = "external_primary";
/** {@hide} */
+ public static final String WAIT_FOR_IDLE_CALL = "wait_for_idle";
+ /** {@hide} */
public static final String SCAN_FILE_CALL = "scan_file";
/** {@hide} */
public static final String SCAN_VOLUME_CALL = "scan_volume";
@@ -3562,6 +3564,17 @@
/** @hide */
@TestApi
+ public static void waitForIdle(Context context) {
+ final ContentResolver resolver = context.getContentResolver();
+ try (ContentProviderClient client = resolver.acquireContentProviderClient(AUTHORITY)) {
+ client.call(WAIT_FOR_IDLE_CALL, null, null);
+ } catch (RemoteException e) {
+ throw e.rethrowAsRuntimeException();
+ }
+ }
+
+ /** @hide */
+ @TestApi
public static Uri scanFile(Context context, File file) {
return scan(context, SCAN_FILE_CALL, file, false);
}
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 7df1ebe..2159cf4 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -7030,6 +7030,8 @@
*/
public static final String DISPLAY_DENSITY_FORCED = "display_density_forced";
+ static final Validator DISPLAY_DENSITY_FORCED_VALIDATOR = NON_NEGATIVE_INTEGER_VALIDATOR;
+
/**
* Setting to always use the default text-to-speech settings regardless
* of the application settings.
@@ -9083,8 +9085,22 @@
};
/**
- * All settings in {@link SETTINGS_TO_BACKUP} array *must* have a non-null validator,
- * otherwise they won't be restored.
+ * The settings values which should only be restored if the target device is the
+ * same as the source device
+ *
+ * NOTE: Settings are backed up and restored in the order they appear
+ * in this array. If you have one setting depending on another,
+ * make sure that they are ordered appropriately.
+ *
+ * @hide
+ */
+ public static final String[] DEVICE_SPECIFIC_SETTINGS_TO_BACKUP = {
+ DISPLAY_DENSITY_FORCED,
+ };
+
+ /**
+ * All settings in {@link SETTINGS_TO_BACKUP} and {@link DEVICE_SPECIFIC_SETTINGS_TO_BACKUP}
+ * array *must* have a non-null validator, otherwise they won't be restored.
*
* @hide
*/
@@ -9276,6 +9292,7 @@
VALIDATORS.put(UI_NIGHT_MODE, UI_NIGHT_MODE_VALIDATOR);
VALIDATORS.put(GLOBAL_ACTIONS_PANEL_ENABLED, GLOBAL_ACTIONS_PANEL_ENABLED_VALIDATOR);
VALIDATORS.put(AWARE_LOCK_ENABLED, AWARE_LOCK_ENABLED_VALIDATOR);
+ VALIDATORS.put(DISPLAY_DENSITY_FORCED, DISPLAY_DENSITY_FORCED_VALIDATOR);
}
/**
@@ -13819,6 +13836,9 @@
* in this array. If you have one setting depending on another,
* make sure that they are ordered appropriately.
*
+ * NOTE: This table should only be used for settings which should be restored
+ * between different types of devices {@see #DEVICE_SPECIFIC_SETTINGS_TO_BACKUP}
+ *
* @hide
*/
public static final String[] SETTINGS_TO_BACKUP = {
@@ -13863,6 +13883,7 @@
* @hide
*/
public static final Map<String, Validator> VALIDATORS = new ArrayMap<>();
+
static {
VALIDATORS.put(APPLY_RAMPING_RINGER, APPLY_RAMPING_RINGER_VALIDATOR);
VALIDATORS.put(BUGREPORT_IN_POWER_MENU, BUGREPORT_IN_POWER_MENU_VALIDATOR);
diff --git a/core/java/android/service/autofill/AutofillFieldClassificationService.java b/core/java/android/service/autofill/AutofillFieldClassificationService.java
index 5f64755..320dcec6 100644
--- a/core/java/android/service/autofill/AutofillFieldClassificationService.java
+++ b/core/java/android/service/autofill/AutofillFieldClassificationService.java
@@ -113,8 +113,9 @@
private final Handler mHandler = new Handler(Looper.getMainLooper(), null, true);
/** @hide */
+ @SystemApi
+ @TestApi
public AutofillFieldClassificationService() {
-
}
@Override
diff --git a/core/java/android/service/autofill/FillContext.java b/core/java/android/service/autofill/FillContext.java
index 70f434c..8331550 100644
--- a/core/java/android/service/autofill/FillContext.java
+++ b/core/java/android/service/autofill/FillContext.java
@@ -30,6 +30,8 @@
import android.util.SparseIntArray;
import android.view.autofill.AutofillId;
+import com.android.internal.util.DataClass;
+
import java.util.LinkedList;
/**
@@ -46,58 +48,36 @@
* to {@link FillResponse.Builder#setClientState(Bundle)} to avoid interpreting
* the UI state again while saving.
*/
+@DataClass(
+ genHiddenConstructor = true,
+ genAidl = false)
public final class FillContext implements Parcelable {
+
+ /**
+ * The id of the {@link FillRequest fill request} this context
+ * corresponds to. This is useful to associate your custom client
+ * state with every request to avoid reinterpreting the UI when saving
+ * user data.
+ */
private final int mRequestId;
+
+ /**
+ * The screen content.
+ */
private final @NonNull AssistStructure mStructure;
+
+ /**
+ * The AutofillId of the view that triggered autofill.
+ */
private final @NonNull AutofillId mFocusedId;
/**
* Lookup table AutofillId->ViewNode to speed up {@link #findViewNodesByAutofillIds}
* This is purely a cache and can be deleted at any time
*/
- @Nullable private ArrayMap<AutofillId, AssistStructure.ViewNode> mViewNodeLookupTable;
+ private transient @Nullable ArrayMap<AutofillId, AssistStructure.ViewNode> mViewNodeLookupTable;
- /** @hide */
- public FillContext(int requestId, @NonNull AssistStructure structure,
- @NonNull AutofillId autofillId) {
- mRequestId = requestId;
- mStructure = structure;
- mFocusedId = autofillId;
- }
-
- private FillContext(Parcel parcel) {
- this(parcel.readInt(), parcel.readParcelable(null), parcel.readParcelable(null));
- }
-
- /**
- * Gets the id of the {@link FillRequest fill request} this context
- * corresponds to. This is useful to associate your custom client
- * state with every request to avoid reinterpreting the UI when saving
- * user data.
- *
- * @return The request id.
- */
- public int getRequestId() {
- return mRequestId;
- }
-
- /**
- * @return The screen content.
- */
- @NonNull
- public AssistStructure getStructure() {
- return mStructure;
- }
-
- /**
- * @return the AutofillId of the view that triggered autofill.
- */
- @NonNull
- public AutofillId getFocusedId() {
- return mFocusedId;
- }
-
@Override
public String toString() {
if (!sDebug) return super.toString();
@@ -105,18 +85,6 @@
return "FillContext [reqId=" + mRequestId + ", focusedId=" + mFocusedId + "]";
}
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel parcel, int flags) {
- parcel.writeInt(mRequestId);
- parcel.writeParcelable(mStructure, flags);
- parcel.writeParcelable(mFocusedId, flags);
- }
-
/**
* Finds {@link ViewNode ViewNodes} that have the requested ids.
*
@@ -190,18 +158,119 @@
return foundNodes;
}
- public static final @android.annotation.NonNull Parcelable.Creator<FillContext> CREATOR =
- new Parcelable.Creator<FillContext>() {
- @Override
- @NonNull
- public FillContext createFromParcel(Parcel parcel) {
- return new FillContext(parcel);
- }
+
+ // Code below generated by codegen v1.0.0.
+ //
+ // DO NOT MODIFY!
+ //
+ // To regenerate run:
+ // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/service/autofill/FillContext.java
+ //
+ // CHECKSTYLE:OFF Generated code
+
+ /**
+ * Creates a new FillContext.
+ *
+ * @param requestId
+ * The id of the {@link FillRequest fill request} this context
+ * corresponds to. This is useful to associate your custom client
+ * state with every request to avoid reinterpreting the UI when saving
+ * user data.
+ * @param structure
+ * The screen content.
+ * @param focusedId
+ * The AutofillId of the view that triggered autofill.
+ * @hide
+ */
+ @DataClass.Generated.Member
+ public FillContext(
+ int requestId,
+ @NonNull AssistStructure structure,
+ @NonNull AutofillId focusedId) {
+ this.mRequestId = requestId;
+ this.mStructure = structure;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mStructure);
+ this.mFocusedId = focusedId;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mFocusedId);
+
+ // onConstructed(); // You can define this method to get a callback
+ }
+
+ /**
+ * The id of the {@link FillRequest fill request} this context
+ * corresponds to. This is useful to associate your custom client
+ * state with every request to avoid reinterpreting the UI when saving
+ * user data.
+ */
+ @DataClass.Generated.Member
+ public int getRequestId() {
+ return mRequestId;
+ }
+
+ /**
+ * The screen content.
+ */
+ @DataClass.Generated.Member
+ public @NonNull AssistStructure getStructure() {
+ return mStructure;
+ }
+
+ /**
+ * The AutofillId of the view that triggered autofill.
+ */
+ @DataClass.Generated.Member
+ public @NonNull AutofillId getFocusedId() {
+ return mFocusedId;
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public void writeToParcel(Parcel dest, int flags) {
+ // You can override field parcelling by defining methods like:
+ // void parcelFieldName(Parcel dest, int flags) { ... }
+
+ dest.writeInt(mRequestId);
+ dest.writeTypedObject(mStructure, flags);
+ dest.writeTypedObject(mFocusedId, flags);
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public int describeContents() { return 0; }
+
+ @DataClass.Generated.Member
+ public static final @NonNull Parcelable.Creator<FillContext> CREATOR
+ = new Parcelable.Creator<FillContext>() {
@Override
- @NonNull
public FillContext[] newArray(int size) {
return new FillContext[size];
}
+
+ @Override
+ @SuppressWarnings({"unchecked", "RedundantCast"})
+ public FillContext createFromParcel(Parcel in) {
+ // You can override field unparcelling by defining methods like:
+ // static FieldType unparcelFieldName(Parcel in) { ... }
+
+ int requestId = in.readInt();
+ AssistStructure structure = (AssistStructure) in.readTypedObject(AssistStructure.CREATOR);
+ AutofillId focusedId = (AutofillId) in.readTypedObject(AutofillId.CREATOR);
+ return new FillContext(
+ requestId,
+ structure,
+ focusedId);
+ }
};
+
+ @DataClass.Generated(
+ time = 1565152135263L,
+ codegenVersion = "1.0.0",
+ sourceFile = "frameworks/base/core/java/android/service/autofill/FillContext.java",
+ inputSignatures = "private final int mRequestId\nprivate final @android.annotation.NonNull android.app.assist.AssistStructure mStructure\nprivate final @android.annotation.NonNull android.view.autofill.AutofillId mFocusedId\nprivate transient @android.annotation.Nullable android.util.ArrayMap<android.view.autofill.AutofillId,android.app.assist.AssistStructure.ViewNode> mViewNodeLookupTable\npublic @java.lang.Override java.lang.String toString()\npublic @android.annotation.NonNull android.app.assist.AssistStructure.ViewNode[] findViewNodesByAutofillIds(android.view.autofill.AutofillId[])\nclass FillContext extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genHiddenConstructor=true, genAidl=false)")
+ @Deprecated
+ private void __metadata() {}
+
}
diff --git a/core/java/android/service/autofill/FillRequest.java b/core/java/android/service/autofill/FillRequest.java
index 91f77ea..e53ebad 100644
--- a/core/java/android/service/autofill/FillRequest.java
+++ b/core/java/android/service/autofill/FillRequest.java
@@ -24,6 +24,7 @@
import android.os.Parcelable;
import android.view.View;
+import com.android.internal.util.DataClass;
import com.android.internal.util.Preconditions;
import java.lang.annotation.Retention;
@@ -39,6 +40,10 @@
*
* @see AutofillService#onFillRequest(FillRequest, android.os.CancellationSignal, FillCallback)
*/
+@DataClass(
+ genToString = true,
+ genHiddenConstructor = true,
+ genHiddenConstDefs = true)
public final class FillRequest implements Parcelable {
/**
@@ -63,54 +68,45 @@
* is called. For example, standard {@link android.widget.TextView} views show an
* {@code AUTOFILL} option in the overflow menu that triggers such request.
*/
- public static final int FLAG_MANUAL_REQUEST = 0x1;
+ public static final @RequestFlags int FLAG_MANUAL_REQUEST = 0x1;
/**
* Indicates this request was made using
* <a href="AutofillService.html#CompatibilityMode">compatibility mode</a>.
*/
- public static final int FLAG_COMPATIBILITY_MODE_REQUEST = 0x2;
+ public static final @RequestFlags int FLAG_COMPATIBILITY_MODE_REQUEST = 0x2;
/** @hide */
public static final int INVALID_REQUEST_ID = Integer.MIN_VALUE;
- /** @hide */
- @IntDef(flag = true, prefix = { "FLAG_" }, value = {
- FLAG_MANUAL_REQUEST, FLAG_COMPATIBILITY_MODE_REQUEST
- })
- @Retention(RetentionPolicy.SOURCE)
- @interface RequestFlags{}
-
- private final int mId;
- private final @RequestFlags int mFlags;
- private final @NonNull ArrayList<FillContext> mContexts;
- private final @Nullable Bundle mClientState;
-
- private FillRequest(@NonNull Parcel parcel) {
- mId = parcel.readInt();
- mContexts = new ArrayList<>();
- parcel.readParcelableList(mContexts, null);
-
- mClientState = parcel.readBundle();
- mFlags = parcel.readInt();
- }
-
- /** @hide */
- public FillRequest(int id, @NonNull ArrayList<FillContext> contexts,
- @Nullable Bundle clientState, @RequestFlags int flags) {
- mId = id;
- mFlags = Preconditions.checkFlagsArgument(flags,
- FLAG_MANUAL_REQUEST | FLAG_COMPATIBILITY_MODE_REQUEST);
- mContexts = Preconditions.checkCollectionElementsNotNull(contexts, "contexts");
- mClientState = clientState;
- }
-
/**
* Gets the unique id of this request.
*/
- public int getId() {
- return mId;
- }
+ private final int mId;
+
+ /**
+ * Gets the contexts associated with each previous fill request.
+ *
+ * <p><b>Note:</b> Starting on Android {@link android.os.Build.VERSION_CODES#Q}, it could also
+ * include contexts from requests whose {@link SaveInfo} had the
+ * {@link SaveInfo#FLAG_DELAY_SAVE} flag.
+ */
+ private final @NonNull List<FillContext> mFillContexts;
+
+ /**
+ * Gets the latest client state bundle set by the service in a
+ * {@link FillResponse.Builder#setClientState(Bundle) fill response}.
+ *
+ * <p><b>Note:</b> Prior to Android {@link android.os.Build.VERSION_CODES#P}, only client state
+ * bundles set by {@link FillResponse.Builder#setClientState(Bundle)} were considered. On
+ * Android {@link android.os.Build.VERSION_CODES#P} and higher, bundles set in the result of
+ * an authenticated request through the
+ * {@link android.view.autofill.AutofillManager#EXTRA_CLIENT_STATE} extra are
+ * also considered (and take precedence when set).
+ *
+ * @return The client state.
+ */
+ private final @Nullable Bundle mClientState;
/**
* Gets the flags associated with this request.
@@ -118,8 +114,105 @@
* @return any combination of {@link #FLAG_MANUAL_REQUEST} and
* {@link #FLAG_COMPATIBILITY_MODE_REQUEST}.
*/
- public @RequestFlags int getFlags() {
- return mFlags;
+ private final @RequestFlags int mFlags;
+
+ private void onConstructed() {
+ Preconditions.checkCollectionElementsNotNull(mFillContexts, "contexts");
+ }
+
+
+
+ // Code below generated by codegen v1.0.0.
+ //
+ // DO NOT MODIFY!
+ //
+ // To regenerate run:
+ // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/service/autofill/FillRequest.java
+ //
+ // CHECKSTYLE:OFF Generated code
+
+ /** @hide */
+ @IntDef(flag = true, prefix = "FLAG_", value = {
+ FLAG_MANUAL_REQUEST,
+ FLAG_COMPATIBILITY_MODE_REQUEST
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ @DataClass.Generated.Member
+ public @interface RequestFlags {}
+
+ /** @hide */
+ @DataClass.Generated.Member
+ public static String requestFlagsToString(@RequestFlags int value) {
+ return com.android.internal.util.BitUtils.flagsToString(
+ value, FillRequest::singleRequestFlagsToString);
+ }
+
+ @DataClass.Generated.Member
+ static String singleRequestFlagsToString(@RequestFlags int value) {
+ switch (value) {
+ case FLAG_MANUAL_REQUEST:
+ return "FLAG_MANUAL_REQUEST";
+ case FLAG_COMPATIBILITY_MODE_REQUEST:
+ return "FLAG_COMPATIBILITY_MODE_REQUEST";
+ default: return Integer.toHexString(value);
+ }
+ }
+
+ /**
+ * Creates a new FillRequest.
+ *
+ * @param id
+ * Gets the unique id of this request.
+ * @param fillContexts
+ * Gets the contexts associated with each previous fill request.
+ *
+ * <p><b>Note:</b> Starting on Android {@link android.os.Build.VERSION_CODES#Q}, it could also
+ * include contexts from requests whose {@link SaveInfo} had the
+ * {@link SaveInfo#FLAG_DELAY_SAVE} flag.
+ * @param clientState
+ * Gets the latest client state bundle set by the service in a
+ * {@link FillResponse.Builder#setClientState(Bundle) fill response}.
+ *
+ * <p><b>Note:</b> Prior to Android {@link android.os.Build.VERSION_CODES#P}, only client state
+ * bundles set by {@link FillResponse.Builder#setClientState(Bundle)} were considered. On
+ * Android {@link android.os.Build.VERSION_CODES#P} and higher, bundles set in the result of
+ * an authenticated request through the
+ * {@link android.view.autofill.AutofillManager#EXTRA_CLIENT_STATE} extra are
+ * also considered (and take precedence when set).
+ * @param flags
+ * Gets the flags associated with this request.
+ *
+ * @return any combination of {@link #FLAG_MANUAL_REQUEST} and
+ * {@link #FLAG_COMPATIBILITY_MODE_REQUEST}.
+ * @hide
+ */
+ @DataClass.Generated.Member
+ public FillRequest(
+ int id,
+ @NonNull List<FillContext> fillContexts,
+ @Nullable Bundle clientState,
+ @RequestFlags int flags) {
+ this.mId = id;
+ this.mFillContexts = fillContexts;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mFillContexts);
+ this.mClientState = clientState;
+ this.mFlags = flags;
+
+ Preconditions.checkFlagsArgument(
+ mFlags,
+ FLAG_MANUAL_REQUEST
+ | FLAG_COMPATIBILITY_MODE_REQUEST);
+
+ onConstructed();
+ }
+
+ /**
+ * Gets the unique id of this request.
+ */
+ @DataClass.Generated.Member
+ public int getId() {
+ return mId;
}
/**
@@ -129,13 +222,9 @@
* include contexts from requests whose {@link SaveInfo} had the
* {@link SaveInfo#FLAG_DELAY_SAVE} flag.
*/
+ @DataClass.Generated.Member
public @NonNull List<FillContext> getFillContexts() {
- return mContexts;
- }
-
- @Override
- public String toString() {
- return "FillRequest: [id=" + mId + ", flags=" + mFlags + ", ctxts= " + mContexts + "]";
+ return mFillContexts;
}
/**
@@ -151,33 +240,89 @@
*
* @return The client state.
*/
+ @DataClass.Generated.Member
public @Nullable Bundle getClientState() {
return mClientState;
}
- @Override
- public int describeContents() {
- return 0;
+ /**
+ * Gets the flags associated with this request.
+ *
+ * @return any combination of {@link #FLAG_MANUAL_REQUEST} and
+ * {@link #FLAG_COMPATIBILITY_MODE_REQUEST}.
+ */
+ @DataClass.Generated.Member
+ public @RequestFlags int getFlags() {
+ return mFlags;
}
@Override
- public void writeToParcel(Parcel parcel, int flags) {
- parcel.writeInt(mId);
- parcel.writeParcelableList(mContexts, flags);
- parcel.writeBundle(mClientState);
- parcel.writeInt(mFlags);
+ @DataClass.Generated.Member
+ public String toString() {
+ // You can override field toString logic by defining methods like:
+ // String fieldNameToString() { ... }
+
+ return "FillRequest { " +
+ "id = " + mId + ", " +
+ "fillContexts = " + mFillContexts + ", " +
+ "clientState = " + mClientState + ", " +
+ "flags = " + requestFlagsToString(mFlags) +
+ " }";
}
- public static final @android.annotation.NonNull Parcelable.Creator<FillRequest> CREATOR =
- new Parcelable.Creator<FillRequest>() {
- @Override
- public FillRequest createFromParcel(Parcel parcel) {
- return new FillRequest(parcel);
- }
+ @Override
+ @DataClass.Generated.Member
+ public void writeToParcel(Parcel dest, int flags) {
+ // You can override field parcelling by defining methods like:
+ // void parcelFieldName(Parcel dest, int flags) { ... }
+ byte flg = 0;
+ if (mClientState != null) flg |= 0x4;
+ dest.writeByte(flg);
+ dest.writeInt(mId);
+ dest.writeParcelableList(mFillContexts, flags);
+ if (mClientState != null) dest.writeBundle(mClientState);
+ dest.writeInt(mFlags);
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public int describeContents() { return 0; }
+
+ @DataClass.Generated.Member
+ public static final @NonNull Parcelable.Creator<FillRequest> CREATOR
+ = new Parcelable.Creator<FillRequest>() {
@Override
public FillRequest[] newArray(int size) {
return new FillRequest[size];
}
+
+ @Override
+ @SuppressWarnings({"unchecked", "RedundantCast"})
+ public FillRequest createFromParcel(Parcel in) {
+ // You can override field unparcelling by defining methods like:
+ // static FieldType unparcelFieldName(Parcel in) { ... }
+
+ byte flg = in.readByte();
+ int id = in.readInt();
+ List<FillContext> fillContexts = new ArrayList<>();
+ in.readParcelableList(fillContexts, FillContext.class.getClassLoader());
+ Bundle clientState = (flg & 0x4) == 0 ? null : in.readBundle();
+ int flags = in.readInt();
+ return new FillRequest(
+ id,
+ fillContexts,
+ clientState,
+ flags);
+ }
};
+
+ @DataClass.Generated(
+ time = 1565152134349L,
+ codegenVersion = "1.0.0",
+ sourceFile = "frameworks/base/core/java/android/service/autofill/FillRequest.java",
+ inputSignatures = "public static final @android.service.autofill.FillRequest.RequestFlags int FLAG_MANUAL_REQUEST\npublic static final @android.service.autofill.FillRequest.RequestFlags int FLAG_COMPATIBILITY_MODE_REQUEST\npublic static final int INVALID_REQUEST_ID\nprivate final int mId\nprivate final @android.annotation.NonNull java.util.List<android.service.autofill.FillContext> mFillContexts\nprivate final @android.annotation.Nullable android.os.Bundle mClientState\nprivate final @android.service.autofill.FillRequest.RequestFlags int mFlags\nprivate void onConstructed()\nclass FillRequest extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genToString=true, genHiddenConstructor=true, genHiddenConstDefs=true)")
+ @Deprecated
+ private void __metadata() {}
+
}
diff --git a/core/java/android/service/notification/NotificationAssistantService.java b/core/java/android/service/notification/NotificationAssistantService.java
index 12d3228..da40254 100644
--- a/core/java/android/service/notification/NotificationAssistantService.java
+++ b/core/java/android/service/notification/NotificationAssistantService.java
@@ -293,6 +293,11 @@
Log.w(TAG, "onNotificationEnqueued: Error receiving StatusBarNotification", e);
return;
}
+ if (sbn == null) {
+ Log.w(TAG, "onNotificationEnqueuedWithChannel: "
+ + "Error receiving StatusBarNotification");
+ return;
+ }
SomeArgs args = SomeArgs.obtain();
args.arg1 = sbn;
@@ -311,6 +316,10 @@
Log.w(TAG, "onNotificationSnoozed: Error receiving StatusBarNotification", e);
return;
}
+ if (sbn == null) {
+ Log.w(TAG, "onNotificationSnoozed: Error receiving StatusBarNotification");
+ return;
+ }
SomeArgs args = SomeArgs.obtain();
args.arg1 = sbn;
diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java
index b44c9d5..78e30ab 100644
--- a/core/java/android/service/notification/NotificationListenerService.java
+++ b/core/java/android/service/notification/NotificationListenerService.java
@@ -1272,6 +1272,10 @@
Log.w(TAG, "onNotificationPosted: Error receiving StatusBarNotification", e);
return;
}
+ if (sbn == null) {
+ Log.w(TAG, "onNotificationPosted: Error receiving StatusBarNotification");
+ return;
+ }
try {
// convert icon metadata to legacy format for older clients
@@ -1313,6 +1317,10 @@
Log.w(TAG, "onNotificationRemoved: Error receiving StatusBarNotification", e);
return;
}
+ if (sbn == null) {
+ Log.w(TAG, "onNotificationRemoved: Error receiving StatusBarNotification");
+ return;
+ }
// protect subclass from concurrent modifications of (@link mNotificationKeys}.
synchronized (mLock) {
applyUpdateLocked(update);
diff --git a/core/java/android/util/FeatureFlagUtils.java b/core/java/android/util/FeatureFlagUtils.java
index 6aef5a5..b66764e 100644
--- a/core/java/android/util/FeatureFlagUtils.java
+++ b/core/java/android/util/FeatureFlagUtils.java
@@ -41,13 +41,14 @@
public static final String SCREENRECORD_LONG_PRESS = "settings_screenrecord_long_press";
public static final String DYNAMIC_SYSTEM = "settings_dynamic_system";
public static final String SETTINGS_WIFITRACKER2 = "settings_wifitracker2";
+ public static final String USE_BUGREPORT_API = "settings_use_bugreport_api";
private static final Map<String, String> DEFAULT_FLAGS;
static {
DEFAULT_FLAGS = new HashMap<>();
DEFAULT_FLAGS.put("settings_audio_switcher", "true");
- DEFAULT_FLAGS.put("settings_call_bugreport_api", "false");
+ DEFAULT_FLAGS.put("settings_use_bugreport_api", "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");
diff --git a/core/java/android/util/LruCache.java b/core/java/android/util/LruCache.java
index f04e7cb..3cbf727d 100644
--- a/core/java/android/util/LruCache.java
+++ b/core/java/android/util/LruCache.java
@@ -17,6 +17,7 @@
package android.util;
import android.annotation.UnsupportedAppUsage;
+
import java.util.LinkedHashMap;
import java.util.Map;
@@ -260,7 +261,7 @@
* @param evicted true if the entry is being removed to make space, false
* if the removal was caused by a {@link #put} or {@link #remove}.
* @param newValue the new value for {@code key}, if it exists. If non-null,
- * this removal was caused by a {@link #put}. Otherwise it was caused by
+ * this removal was caused by a {@link #put} or a {@link #get}. Otherwise it was caused by
* an eviction or a {@link #remove}.
*/
protected void entryRemoved(boolean evicted, K key, V oldValue, V newValue) {}
diff --git a/core/java/android/view/FrameMetrics.java b/core/java/android/view/FrameMetrics.java
index dcdef3e..ea66656 100644
--- a/core/java/android/view/FrameMetrics.java
+++ b/core/java/android/view/FrameMetrics.java
@@ -220,7 +220,7 @@
int SWAP_BUFFERS = 12;
int FRAME_COMPLETED = 13;
- int FRAME_STATS_COUNT = 16; // must always be last
+ int FRAME_STATS_COUNT = 17; // must always be last
}
/*
diff --git a/core/java/android/view/IRecentsAnimationRunner.aidl b/core/java/android/view/IRecentsAnimationRunner.aidl
index 6cda60c..724d96e 100644
--- a/core/java/android/view/IRecentsAnimationRunner.aidl
+++ b/core/java/android/view/IRecentsAnimationRunner.aidl
@@ -16,6 +16,7 @@
package android.view;
+import android.app.ActivityManager;
import android.graphics.Rect;
import android.view.RemoteAnimationTarget;
import android.view.IRecentsAnimationController;
@@ -33,16 +34,16 @@
* wallpaper not drawing in time, or the handler not finishing the animation within a predefined
* amount of time.
*
- * @param deferredWithScreenshot If set to {@code true}, the contents of the task will be
- * replaced with a screenshot, such that the runner's leash is
- * still active. As soon as the runner doesn't need the leash
- * anymore, it must call
- * {@link IRecentsAnimationController#cleanupScreenshot).
+ * @param taskSnapshot If the snapshot is null, the animation will be cancelled and the leash
+ * will be inactive immediately. Otherwise, the contents of the task will be
+ * replaced with {@param taskSnapshot}, such that the runner's leash is
+ * still active. As soon as the runner doesn't need the leash anymore, it
+ * must call {@link IRecentsAnimationController#cleanupScreenshot).
*
* @see {@link RecentsAnimationController#cleanupScreenshot}
*/
@UnsupportedAppUsage
- void onAnimationCanceled(boolean deferredWithScreenshot) = 1;
+ void onAnimationCanceled(in @nullable ActivityManager.TaskSnapshot taskSnapshot) = 1;
/**
* Called when the system is ready for the handler to start animating all the visible tasks.
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 1779a80..6d4128b 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -13386,10 +13386,10 @@
if ((mPrivateFlags2 & PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED) == 0) {
mPrivateFlags2 |= PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
- if (mParent != null) {
+ if (mParent != null && mParent instanceof View) {
try {
mParent.notifySubtreeAccessibilityStateChanged(
- this, this, AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE);
+ this, (View) mParent, AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE);
} catch (AbstractMethodError e) {
Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
" does not fully implement ViewParent", e);
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 82a5fa9..7ee8865 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -5144,7 +5144,7 @@
}
if (child.getVisibility() != View.GONE) {
- notifySubtreeAccessibilityStateChangedIfNeeded();
+ child.notifySubtreeAccessibilityStateChangedIfNeeded();
}
if (mTransientIndices != null) {
@@ -5432,7 +5432,7 @@
dispatchViewRemoved(view);
if (view.getVisibility() != View.GONE) {
- notifySubtreeAccessibilityStateChangedIfNeeded();
+ view.notifySubtreeAccessibilityStateChangedIfNeeded();
}
int transientCount = mTransientIndices == null ? 0 : mTransientIndices.size();
@@ -5740,7 +5740,7 @@
}
dispatchVisibilityAggregated(isAttachedToWindow() && getWindowVisibility() == VISIBLE
&& isShown());
- notifySubtreeAccessibilityStateChangedIfNeeded();
+ child.notifySubtreeAccessibilityStateChangedIfNeeded();
}
/**
@@ -6146,7 +6146,8 @@
if (invalidate) {
invalidateViewProperty(false, false);
}
- notifySubtreeAccessibilityStateChangedIfNeeded();
+ notifySubtreeAccessibilityStateChanged(
+ this, this, AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE);
}
@Override
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 85e9e49..fe88a91 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -2550,12 +2550,10 @@
return;
}
- final boolean isItemEnabled;
+ boolean isItemEnabled = view.isEnabled() && isEnabled();
final ViewGroup.LayoutParams lp = view.getLayoutParams();
if (lp instanceof AbsListView.LayoutParams) {
- isItemEnabled = ((AbsListView.LayoutParams) lp).isEnabled && isEnabled();
- } else {
- isItemEnabled = false;
+ isItemEnabled &= ((AbsListView.LayoutParams) lp).isEnabled;
}
info.setEnabled(isItemEnabled);
diff --git a/core/java/android/widget/AbsSeekBar.java b/core/java/android/widget/AbsSeekBar.java
index c3e08fc..bbcba2e 100644
--- a/core/java/android/widget/AbsSeekBar.java
+++ b/core/java/android/widget/AbsSeekBar.java
@@ -91,6 +91,7 @@
@UnsupportedAppUsage
private float mDisabledAlpha;
+ private int mThumbExclusionMaxSize;
private int mScaledTouchSlop;
private float mTouchDownX;
@UnsupportedAppUsage
@@ -171,6 +172,8 @@
applyTickMarkTint();
mScaledTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
+ mThumbExclusionMaxSize = getResources().getDimensionPixelSize(
+ com.android.internal.R.dimen.seekbar_thumb_exclusion_max_size);
}
/**
@@ -763,12 +766,30 @@
}
mGestureExclusionRects.clear();
thumb.copyBounds(mThumbRect);
+ mThumbRect.offset(mPaddingLeft - mThumbOffset, mPaddingTop);
+ growRectTo(mThumbRect, Math.min(getHeight(), mThumbExclusionMaxSize));
mGestureExclusionRects.add(mThumbRect);
mGestureExclusionRects.addAll(mUserGestureExclusionRects);
super.setSystemGestureExclusionRects(mGestureExclusionRects);
}
/**
+ * Grows {@code r} from its center such that each dimension is at least {@code minimumSize}.
+ */
+ private void growRectTo(Rect r, int minimumSize) {
+ int dy = (minimumSize - r.height()) / 2;
+ if (dy > 0) {
+ r.top -= dy;
+ r.bottom += dy;
+ }
+ int dx = (minimumSize - r.width()) / 2;
+ if (dx > 0) {
+ r.left -= dx;
+ r.right += dx;
+ }
+ }
+
+ /**
* @hide
*/
@Override
diff --git a/core/java/android/widget/AdapterView.java b/core/java/android/widget/AdapterView.java
index c55f7d6..5359e27 100644
--- a/core/java/android/widget/AdapterView.java
+++ b/core/java/android/widget/AdapterView.java
@@ -1106,7 +1106,8 @@
checkSelectionChanged();
}
- notifySubtreeAccessibilityStateChangedIfNeeded();
+ notifySubtreeAccessibilityStateChanged(
+ this, this, AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE);
}
/**
diff --git a/core/java/android/widget/TabHost.java b/core/java/android/widget/TabHost.java
index 90cb1c8..45e635ebe 100644
--- a/core/java/android/widget/TabHost.java
+++ b/core/java/android/widget/TabHost.java
@@ -59,13 +59,21 @@
private static final int TABWIDGET_LOCATION_BOTTOM = 3;
private TabWidget mTabWidget;
private FrameLayout mTabContent;
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(trackingBug = 137825207, maxTargetSdk = Build.VERSION_CODES.Q,
+ publicAlternatives = "Use {@code androidx.viewpager.widget.ViewPager} and "
+ + "{@code com.google.android.material.tabs.TabLayout} instead.\n"
+ + "See <a href=\"{@docRoot}guide/navigation/navigation-swipe-view"
+ + "\">TabLayout and ViewPager</a>")
private List<TabSpec> mTabSpecs = new ArrayList<TabSpec>(2);
/**
* This field should be made private, so it is hidden from the SDK.
* {@hide}
*/
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(trackingBug = 137825207, maxTargetSdk = Build.VERSION_CODES.Q,
+ publicAlternatives = "Use {@code androidx.viewpager.widget.ViewPager} and "
+ + "{@code com.google.android.material.tabs.TabLayout} instead.\n"
+ + "See <a href=\"{@docRoot}guide/navigation/navigation-swipe-view"
+ + "\">TabLayout and ViewPager</a>")
protected int mCurrentTab = -1;
private View mCurrentView = null;
/**
@@ -73,7 +81,11 @@
* {@hide}
*/
protected LocalActivityManager mLocalActivityManager = null;
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(trackingBug = 137825207, maxTargetSdk = Build.VERSION_CODES.Q,
+ publicAlternatives = "Use {@code androidx.viewpager.widget.ViewPager} and "
+ + "{@code com.google.android.material.tabs.TabLayout} instead.\n"
+ + "See <a href=\"{@docRoot}guide/navigation/navigation-swipe-view"
+ + "\">TabLayout and ViewPager</a>")
private OnTabChangeListener mOnTabChangeListener;
private OnKeyListener mTabKeyListener;
@@ -514,9 +526,17 @@
private final @NonNull String mTag;
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(trackingBug = 137825207, maxTargetSdk = Build.VERSION_CODES.Q,
+ publicAlternatives = "Use {@code androidx.viewpager.widget.ViewPager} and "
+ + "{@code com.google.android.material.tabs.TabLayout} instead.\n"
+ + "See <a href=\"{@docRoot}guide/navigation/navigation-swipe-view"
+ + "\">TabLayout and ViewPager</a>")
private IndicatorStrategy mIndicatorStrategy;
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(trackingBug = 137825207, maxTargetSdk = Build.VERSION_CODES.Q,
+ publicAlternatives = "Use {@code androidx.viewpager.widget.ViewPager} and "
+ + "{@code com.google.android.material.tabs.TabLayout} instead.\n"
+ + "See <a href=\"{@docRoot}guide/navigation/navigation-swipe-view"
+ + "\">TabLayout and ViewPager</a>")
private ContentStrategy mContentStrategy;
/**
@@ -779,7 +799,11 @@
mIntent = intent;
}
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(trackingBug = 137825207, maxTargetSdk = Build.VERSION_CODES.Q,
+ publicAlternatives = "Use {@code androidx.viewpager.widget.ViewPager} and "
+ + "{@code com.google.android.material.tabs.TabLayout} instead.\n"
+ + "See <a href=\"{@docRoot}guide/navigation/navigation-swipe-view"
+ + "\">TabLayout and ViewPager</a>")
public View getContentView() {
if (mLocalActivityManager == null) {
throw new IllegalStateException("Did you forget to call 'public void setup(LocalActivityManager activityGroup)'?");
@@ -809,7 +833,11 @@
return mLaunchedView;
}
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(trackingBug = 137825207, maxTargetSdk = Build.VERSION_CODES.Q,
+ publicAlternatives = "Use {@code androidx.viewpager.widget.ViewPager} and "
+ + "{@code com.google.android.material.tabs.TabLayout} instead.\n"
+ + "See <a href=\"{@docRoot}guide/navigation/navigation-swipe-view"
+ + "\">TabLayout and ViewPager</a>")
public void tabClosed() {
if (mLaunchedView != null) {
mLaunchedView.setVisibility(View.GONE);
diff --git a/core/java/android/widget/TabWidget.java b/core/java/android/widget/TabWidget.java
index 434a799..bd0d039 100644
--- a/core/java/android/widget/TabWidget.java
+++ b/core/java/android/widget/TabWidget.java
@@ -65,7 +65,11 @@
private OnTabSelectionChanged mSelectionChangedListener;
// This value will be set to 0 as soon as the first tab is added to TabHost.
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(trackingBug = 137825207, maxTargetSdk = Build.VERSION_CODES.Q,
+ publicAlternatives = "Use {@code androidx.viewpager.widget.ViewPager} and "
+ + "{@code com.google.android.material.tabs.TabLayout} instead.\n"
+ + "See <a href=\"{@docRoot}guide/navigation/navigation-swipe-view"
+ + "\">TabLayout and ViewPager</a>")
private int mSelectedTab = -1;
@Nullable
@@ -74,7 +78,11 @@
@Nullable
private Drawable mRightStrip;
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(trackingBug = 137825207, maxTargetSdk = Build.VERSION_CODES.Q,
+ publicAlternatives = "Use {@code androidx.viewpager.widget.ViewPager} and "
+ + "{@code com.google.android.material.tabs.TabLayout} instead.\n"
+ + "See <a href=\"{@docRoot}guide/navigation/navigation-swipe-view"
+ + "\">TabLayout and ViewPager</a>")
private boolean mDrawBottomStrips = true;
private boolean mStripMoved;
@@ -551,7 +559,11 @@
* Provides a way for {@link TabHost} to be notified that the user clicked
* on a tab indicator.
*/
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(trackingBug = 137825207, maxTargetSdk = Build.VERSION_CODES.Q,
+ publicAlternatives = "Use {@code androidx.viewpager.widget.ViewPager} and "
+ + "{@code com.google.android.material.tabs.TabLayout} instead.\n"
+ + "See <a href=\"{@docRoot}guide/navigation/navigation-swipe-view"
+ + "\">TabLayout and ViewPager</a>")
void setTabSelectionListener(OnTabSelectionChanged listener) {
mSelectionChangedListener = listener;
}
diff --git a/core/java/com/android/internal/app/AssistUtils.java b/core/java/com/android/internal/app/AssistUtils.java
index efcdb9a..f848309 100644
--- a/core/java/com/android/internal/app/AssistUtils.java
+++ b/core/java/com/android/internal/app/AssistUtils.java
@@ -195,7 +195,7 @@
return applicationInfo.isSystemApp() || applicationInfo.isUpdatedSystemApp();
}
- private static boolean isDisclosureEnabled(Context context) {
+ public static boolean isDisclosureEnabled(Context context) {
return Settings.Secure.getInt(context.getContentResolver(),
Settings.Secure.ASSIST_DISCLOSURE_ENABLED, 0) != 0;
}
diff --git a/core/java/com/android/internal/colorextraction/ColorExtractor.java b/core/java/com/android/internal/colorextraction/ColorExtractor.java
index 3003ce8..f0da0d5 100644
--- a/core/java/com/android/internal/colorextraction/ColorExtractor.java
+++ b/core/java/com/android/internal/colorextraction/ColorExtractor.java
@@ -73,8 +73,10 @@
}
mOnColorsChangedListeners = new ArrayList<>();
- wallpaperManager.addOnColorsChangedListener(this, null /* handler */);
- initExtractColors(wallpaperManager, immediately);
+ if (wallpaperManager.isWallpaperSupported()) {
+ wallpaperManager.addOnColorsChangedListener(this, null /* handler */);
+ initExtractColors(wallpaperManager, immediately);
+ }
}
private void initExtractColors(WallpaperManager wallpaperManager, boolean immediately) {
diff --git a/core/java/com/android/internal/content/PackageHelper.java b/core/java/com/android/internal/content/PackageHelper.java
index 1d81c59..152d699 100644
--- a/core/java/com/android/internal/content/PackageHelper.java
+++ b/core/java/com/android/internal/content/PackageHelper.java
@@ -35,7 +35,7 @@
import android.os.storage.StorageVolume;
import android.os.storage.VolumeInfo;
import android.provider.Settings;
-import android.util.ArraySet;
+import android.util.ArrayMap;
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
@@ -166,6 +166,23 @@
params.sizeBytes, testableInterface);
}
+ private static boolean checkFitOnVolume(StorageManager storageManager, String volumePath,
+ SessionParams params) throws IOException {
+ if (volumePath == null) {
+ return false;
+ }
+ final int installFlags = translateAllocateFlags(params.installFlags);
+ final UUID target = storageManager.getUuidForPath(new File(volumePath));
+ final long availBytes = storageManager.getAllocatableBytes(target,
+ installFlags | StorageManager.FLAG_ALLOCATE_NON_CACHE_ONLY);
+ if (params.sizeBytes <= availBytes) {
+ return true;
+ }
+ final long cacheClearable = storageManager.getAllocatableBytes(target,
+ installFlags | StorageManager.FLAG_ALLOCATE_CACHE_ONLY);
+ return params.sizeBytes <= availBytes + cacheClearable;
+ }
+
@VisibleForTesting
public static String resolveInstallVolume(Context context, SessionParams params,
TestableInterface testInterface) throws IOException {
@@ -178,35 +195,23 @@
ApplicationInfo existingInfo = testInterface.getExistingAppInfo(context,
params.appPackageName);
- // Figure out best candidate volume, and also if we fit on internal
- final ArraySet<String> allCandidates = new ArraySet<>();
- boolean fitsOnInternal = false;
- VolumeInfo bestCandidate = null;
- long bestCandidateAvailBytes = Long.MIN_VALUE;
+ final ArrayMap<String, String> volumePaths = new ArrayMap<>();
+ String internalVolumePath = null;
for (VolumeInfo vol : storageManager.getVolumes()) {
if (vol.type == VolumeInfo.TYPE_PRIVATE && vol.isMountedWritable()) {
final boolean isInternalStorage = ID_PRIVATE_INTERNAL.equals(vol.id);
- final UUID target = storageManager.getUuidForPath(new File(vol.path));
- final long availBytes = storageManager.getAllocatableBytes(target,
- translateAllocateFlags(params.installFlags));
if (isInternalStorage) {
- fitsOnInternal = (params.sizeBytes <= availBytes);
+ internalVolumePath = vol.path;
}
if (!isInternalStorage || allow3rdPartyOnInternal) {
- if (availBytes >= params.sizeBytes) {
- allCandidates.add(vol.fsUuid);
- }
- if (availBytes >= bestCandidateAvailBytes) {
- bestCandidate = vol;
- bestCandidateAvailBytes = availBytes;
- }
+ volumePaths.put(vol.fsUuid, vol.path);
}
}
}
// System apps always forced to internal storage
if (existingInfo != null && existingInfo.isSystemApp()) {
- if (fitsOnInternal) {
+ if (checkFitOnVolume(storageManager, internalVolumePath, params)) {
return StorageManager.UUID_PRIVATE_INTERNAL;
} else {
throw new IOException("Not enough space on existing volume "
@@ -228,7 +233,7 @@
throw new IOException("Not allowed to install non-system apps on internal storage");
}
- if (fitsOnInternal) {
+ if (checkFitOnVolume(storageManager, internalVolumePath, params)) {
return StorageManager.UUID_PRIVATE_INTERNAL;
} else {
throw new IOException("Requested internal only, but not enough space");
@@ -237,10 +242,14 @@
// If app already exists somewhere, we must stay on that volume
if (existingInfo != null) {
- if (Objects.equals(existingInfo.volumeUuid, StorageManager.UUID_PRIVATE_INTERNAL)
- && fitsOnInternal) {
- return StorageManager.UUID_PRIVATE_INTERNAL;
- } else if (allCandidates.contains(existingInfo.volumeUuid)) {
+ String existingVolumePath = null;
+ if (Objects.equals(existingInfo.volumeUuid, StorageManager.UUID_PRIVATE_INTERNAL)) {
+ existingVolumePath = internalVolumePath;
+ } else if (volumePaths.containsKey(existingInfo.volumeUuid)) {
+ existingVolumePath = volumePaths.get(existingInfo.volumeUuid);
+ }
+
+ if (checkFitOnVolume(storageManager, existingVolumePath, params)) {
return existingInfo.volumeUuid;
} else {
throw new IOException("Not enough space on existing volume "
@@ -250,12 +259,36 @@
// We're left with new installations with either preferring external or auto, so just pick
// volume with most space
- if (bestCandidate != null) {
- return bestCandidate.fsUuid;
+ if (volumePaths.size() == 1) {
+ if (checkFitOnVolume(storageManager, volumePaths.valueAt(0), params)) {
+ return volumePaths.keyAt(0);
+ }
} else {
- throw new IOException("No special requests, but no room on allowed volumes. "
- + " allow3rdPartyOnInternal? " + allow3rdPartyOnInternal);
+ String bestCandidate = null;
+ long bestCandidateAvailBytes = Long.MIN_VALUE;
+ for (String vol : volumePaths.keySet()) {
+ final String volumePath = volumePaths.get(vol);
+ final UUID target = storageManager.getUuidForPath(new File(volumePath));
+
+ // We need to take into account freeable cached space, because we're choosing the
+ // best candidate amongst a list, not just checking if we fit at all.
+ final long availBytes = storageManager.getAllocatableBytes(target,
+ translateAllocateFlags(params.installFlags));
+
+ if (availBytes >= bestCandidateAvailBytes) {
+ bestCandidate = vol;
+ bestCandidateAvailBytes = availBytes;
+ }
+ }
+
+ if (bestCandidateAvailBytes >= params.sizeBytes) {
+ return bestCandidate;
+ }
+
}
+
+ throw new IOException("No special requests, but no room on allowed volumes. "
+ + " allow3rdPartyOnInternal? " + allow3rdPartyOnInternal);
}
public static boolean fitsOnInternal(Context context, SessionParams params) throws IOException {
diff --git a/core/java/com/android/internal/os/AtomicDirectory.java b/core/java/com/android/internal/os/AtomicDirectory.java
index f24d12e..ebcee15 100644
--- a/core/java/com/android/internal/os/AtomicDirectory.java
+++ b/core/java/com/android/internal/os/AtomicDirectory.java
@@ -23,6 +23,8 @@
import com.android.internal.util.Preconditions;
+import libcore.io.IoUtils;
+
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
@@ -136,10 +138,11 @@
if (file.isDirectory() || !file.getParentFile().equals(getOrCreateBaseDirectory())) {
throw new IllegalArgumentException("Must be a file in " + getOrCreateBaseDirectory());
}
- final FileOutputStream destination = new FileOutputStream(file);
- if (mOpenFiles.put(file, destination) != null) {
+ if (mOpenFiles.containsKey(file)) {
throw new IllegalArgumentException("Already open file" + file.getCanonicalPath());
}
+ final FileOutputStream destination = new FileOutputStream(file);
+ mOpenFiles.put(file, destination);
return destination;
}
@@ -152,20 +155,21 @@
*/
public void closeWrite(@NonNull FileOutputStream destination) {
final int indexOfValue = mOpenFiles.indexOfValue(destination);
- if (mOpenFiles.removeAt(indexOfValue) == null) {
+ if (indexOfValue < 0) {
throw new IllegalArgumentException("Unknown file stream " + destination);
}
+ mOpenFiles.removeAt(indexOfValue);
FileUtils.sync(destination);
- try {
- destination.close();
- } catch (IOException ignored) {}
+ IoUtils.closeQuietly(destination);
}
public void failWrite(@NonNull FileOutputStream destination) {
final int indexOfValue = mOpenFiles.indexOfValue(destination);
- if (indexOfValue >= 0) {
- mOpenFiles.removeAt(indexOfValue);
+ if (indexOfValue < 0) {
+ throw new IllegalArgumentException("Unknown file stream " + destination);
}
+ mOpenFiles.removeAt(indexOfValue);
+ IoUtils.closeQuietly(destination);
}
/**
diff --git a/core/java/com/android/internal/os/ZygoteArguments.java b/core/java/com/android/internal/os/ZygoteArguments.java
index 6d40266..abc4160 100644
--- a/core/java/com/android/internal/os/ZygoteArguments.java
+++ b/core/java/com/android/internal/os/ZygoteArguments.java
@@ -187,6 +187,11 @@
boolean mPidQuery;
/**
+ * Whether the current arguments constitute a notification that boot completed.
+ */
+ boolean mBootCompleted;
+
+ /**
* Exemptions from API blacklisting. These are sent to the pre-forked zygote at boot time, or
* when they change, via --set-api-blacklist-exemptions.
*/
@@ -361,6 +366,8 @@
mAbiListQuery = true;
} else if (arg.equals("--get-pid")) {
mPidQuery = true;
+ } else if (arg.equals("--boot-completed")) {
+ mBootCompleted = true;
} else if (arg.startsWith("--instruction-set=")) {
mInstructionSet = getAssignmentValue(arg);
} else if (arg.startsWith("--app-data-dir=")) {
@@ -417,7 +424,11 @@
}
}
- if (mAbiListQuery || mPidQuery) {
+ if (mBootCompleted) {
+ if (args.length - curArg > 0) {
+ throw new IllegalArgumentException("Unexpected arguments after --boot-completed");
+ }
+ } else if (mAbiListQuery || mPidQuery) {
if (args.length - curArg > 0) {
throw new IllegalArgumentException("Unexpected arguments after --query-abi-list.");
}
diff --git a/core/java/com/android/internal/os/ZygoteConnection.java b/core/java/com/android/internal/os/ZygoteConnection.java
index 06a14f0..b3ec5f5 100644
--- a/core/java/com/android/internal/os/ZygoteConnection.java
+++ b/core/java/com/android/internal/os/ZygoteConnection.java
@@ -140,6 +140,11 @@
ZygoteArguments parsedArgs = new ZygoteArguments(args);
+ if (parsedArgs.mBootCompleted) {
+ handleBootCompleted();
+ return null;
+ }
+
if (parsedArgs.mAbiListQuery) {
handleAbiListQuery();
return null;
@@ -300,6 +305,10 @@
}
}
+ private void handleBootCompleted() {
+ VMRuntime.bootCompleted();
+ }
+
/**
* Preloads resources if the zygote is in lazily preload mode. Writes the result of the
* preload operation; {@code 0} when a preload was initiated due to this request and {@code 1}
diff --git a/core/java/com/android/internal/util/DataClass.java b/core/java/com/android/internal/util/DataClass.java
index da33f99..43539c7 100644
--- a/core/java/com/android/internal/util/DataClass.java
+++ b/core/java/com/android/internal/util/DataClass.java
@@ -65,11 +65,21 @@
boolean genGetters() default true;
/**
+ * {@link #genGetters} with @hide
+ */
+ boolean genHiddenGetters() default false;
+
+ /**
* Generates setters for each field.
*/
boolean genSetters() default false;
/**
+ * {@link #genSetters} with @hide
+ */
+ boolean genHiddenSetters() default false;
+
+ /**
* Generates a public constructor with each field initialized from a parameter and optionally
* some user-defined state validation at the end.
*
@@ -85,6 +95,11 @@
boolean genConstructor() default true;
/**
+ * {@link #genConstructor} with @hide
+ */
+ boolean genHiddenConstructor() default false;
+
+ /**
* Generates a Builder for your class.
*
* Uses a package-private constructor under the hood, so same rules hold as for
@@ -93,6 +108,11 @@
boolean genBuilder() default false;
/**
+ * {@link #genBuilder} with @hide
+ */
+ boolean genHiddenBuilder() default false;
+
+ /**
* Generates a structural {@link Object#equals} + {@link Object#hashCode}.
*
* You can customize individual fields' logic by declaring methods like:
@@ -126,6 +146,11 @@
boolean genCopyConstructor() default false;
/**
+ * {@link #genCopyConstructor} with @hide
+ */
+ boolean genHiddenCopyConstructor() default false;
+
+ /**
* Generates constant annotations({@link IntDef}/{@link StringDef}) for any constant groups
* with common prefix.
* The annotation names are based on the common prefix.
@@ -146,6 +171,11 @@
*/
boolean genConstDefs() default true;
+ /**
+ * {@link #genConstDefs} with @hide
+ */
+ boolean genHiddenConstDefs() default false;
+
/**
* Allows specifying custom parcelling logic based on reusable
diff --git a/core/java/com/android/internal/util/StatLogger.java b/core/java/com/android/internal/util/StatLogger.java
index 1dac136..ca6acd6 100644
--- a/core/java/com/android/internal/util/StatLogger.java
+++ b/core/java/com/android/internal/util/StatLogger.java
@@ -163,6 +163,9 @@
proto.write(Event.LABEL, mLabels[i]);
proto.write(Event.COUNT, mCountStats[i]);
proto.write(Event.TOTAL_DURATION_MICROS, mDurationStats[i]);
+ proto.write(Event.MAX_CALLS_PER_SECOND, mMaxCallsPerSecond[i]);
+ proto.write(Event.MAX_DURATION_PER_SECOND_MICROS, mMaxDurationPerSecond[i]);
+ proto.write(Event.MAX_DURATION_STATS_MICROS, mMaxDurationStats[i]);
proto.end(inner);
}
diff --git a/core/java/com/android/internal/widget/MediaNotificationView.java b/core/java/com/android/internal/widget/MediaNotificationView.java
index e7d240a..9bb4501 100644
--- a/core/java/com/android/internal/widget/MediaNotificationView.java
+++ b/core/java/com/android/internal/widget/MediaNotificationView.java
@@ -26,6 +26,8 @@
import android.widget.ImageView;
import android.widget.RemoteViews;
+import java.util.ArrayList;
+
/**
* A TextView that can float around an image on the end.
*
@@ -42,6 +44,7 @@
private View mMainColumn;
private View mMediaContent;
private int mImagePushIn;
+ private ArrayList<VisibilityChangeListener> mListeners;
public MediaNotificationView(Context context) {
this(context, null);
@@ -168,4 +171,50 @@
mMainColumn = findViewById(com.android.internal.R.id.notification_main_column);
mMediaContent = findViewById(com.android.internal.R.id.notification_media_content);
}
+
+ @Override
+ public void onVisibilityAggregated(boolean isVisible) {
+ super.onVisibilityAggregated(isVisible);
+ if (mListeners != null) {
+ for (int i = 0; i < mListeners.size(); i++) {
+ mListeners.get(i).onAggregatedVisibilityChanged(isVisible);
+ }
+ }
+ }
+
+ /**
+ * Add a listener to receive updates on the visibility of this view
+ *
+ * @param listener The listener to add.
+ */
+ public void addVisibilityListener(VisibilityChangeListener listener) {
+ if (mListeners == null) {
+ mListeners = new ArrayList<>();
+ }
+ if (!mListeners.contains(listener)) {
+ mListeners.add(listener);
+ }
+ }
+
+ /**
+ * Remove the specified listener
+ *
+ * @param listener The listener to remove.
+ */
+ public void removeVisibilityListener(VisibilityChangeListener listener) {
+ if (mListeners != null) {
+ mListeners.remove(listener);
+ }
+ }
+
+ /**
+ * Interface for receiving updates when the view's visibility changes
+ */
+ public interface VisibilityChangeListener {
+ /**
+ * Method called when the visibility of this view has changed
+ * @param isVisible true if the view is now visible
+ */
+ void onAggregatedVisibilityChanged(boolean isVisible);
+ }
}
diff --git a/core/jni/Android.bp b/core/jni/Android.bp
index 844a898..a542475 100644
--- a/core/jni/Android.bp
+++ b/core/jni/Android.bp
@@ -104,6 +104,7 @@
"android_database_SQLiteConnection.cpp",
"android_database_SQLiteGlobal.cpp",
"android_database_SQLiteDebug.cpp",
+ "android_graphics_GraphicBuffer.cpp",
"android_view_CompositionSamplingListener.cpp",
"android_view_DisplayEventReceiver.cpp",
"android_view_InputChannel.cpp",
@@ -421,7 +422,6 @@
"android_view_ThreadedRenderer.cpp",
"android/graphics/BitmapRegionDecoder.cpp",
"android/graphics/GIFMovie.cpp",
- "android/graphics/GraphicBuffer.cpp",
"android/graphics/Movie.cpp",
"android/graphics/MovieImpl.cpp",
"android/graphics/SurfaceTexture.cpp",
diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp
index f3abcf1..78e8e13 100755
--- a/core/jni/android/graphics/Bitmap.cpp
+++ b/core/jni/android/graphics/Bitmap.cpp
@@ -19,11 +19,10 @@
#include <utils/Color.h>
#ifdef __ANDROID__ // Layoutlib does not support graphic buffer, parcel or render thread
-#include "GraphicBuffer.h"
#include <binder/Parcel.h>
#include <renderthread/RenderProxy.h>
+#include <android_runtime/android_graphics_GraphicBuffer.h>
#include <android_runtime/android_hardware_HardwareBuffer.h>
-
#include <private/android/AHardwareBufferHelpers.h>
#endif
@@ -1129,12 +1128,10 @@
static jobject Bitmap_wrapHardwareBufferBitmap(JNIEnv* env, jobject, jobject hardwareBuffer,
jlong colorSpacePtr) {
#ifdef __ANDROID__ // Layoutlib does not support graphic buffer
- AHardwareBuffer* hwBuf = android_hardware_HardwareBuffer_getNativeHardwareBuffer(env,
+ AHardwareBuffer* buffer = android_hardware_HardwareBuffer_getNativeHardwareBuffer(env,
hardwareBuffer);
- sp<GraphicBuffer> buffer(AHardwareBuffer_to_GraphicBuffer(hwBuf));
- SkColorType ct = uirenderer::PixelFormatToColorType(buffer->getPixelFormat());
- sk_sp<Bitmap> bitmap = Bitmap::createFrom(buffer, ct,
- GraphicsJNI::getNativeColorSpace(colorSpacePtr));
+ sk_sp<Bitmap> bitmap = Bitmap::createFrom(buffer,
+ GraphicsJNI::getNativeColorSpace(colorSpacePtr));
if (!bitmap.get()) {
ALOGW("failed to create hardware bitmap from hardware buffer");
return NULL;
@@ -1151,9 +1148,8 @@
LOG_ALWAYS_FATAL_IF(!bitmapHandle->isHardware(),
"Hardware config is only supported config in Bitmap_getGraphicBuffer");
- Bitmap& hwuiBitmap = bitmapHandle->bitmap();
- sp<GraphicBuffer> buffer(hwuiBitmap.graphicBuffer());
- return createJavaGraphicBuffer(env, buffer);
+ Bitmap& bitmap = bitmapHandle->bitmap();
+ return android_graphics_GraphicBuffer_createFromAHardwareBuffer(env, bitmap.hardwareBuffer());
#else
return NULL;
#endif
diff --git a/core/jni/android_app_ActivityThread.cpp b/core/jni/android_app_ActivityThread.cpp
index 3a08148..5f83038 100644
--- a/core/jni/android_app_ActivityThread.cpp
+++ b/core/jni/android_app_ActivityThread.cpp
@@ -36,7 +36,6 @@
android_app_ActivityThread_dumpGraphics(JNIEnv* env, jobject clazz, jobject javaFileDescriptor) {
int fd = jniGetFDFromFileDescriptor(env, javaFileDescriptor);
android::uirenderer::renderthread::RenderProxy::dumpGraphicsMemory(fd);
- minikin::Layout::dumpMinikinStats(fd);
}
static void android_app_ActivityThread_initZygoteChildHeapProfiling(JNIEnv* env, jobject clazz) {
diff --git a/core/jni/android/graphics/GraphicBuffer.cpp b/core/jni/android_graphics_GraphicBuffer.cpp
similarity index 95%
rename from core/jni/android/graphics/GraphicBuffer.cpp
rename to core/jni/android_graphics_GraphicBuffer.cpp
index 344e22c..bb9254c 100644
--- a/core/jni/android/graphics/GraphicBuffer.cpp
+++ b/core/jni/android_graphics_GraphicBuffer.cpp
@@ -21,10 +21,10 @@
#include <inttypes.h>
#include "android_os_Parcel.h"
-#include "GraphicBuffer.h"
-#include "GraphicsJNI.h"
+#include "android/graphics/GraphicsJNI.h"
#include <android_runtime/AndroidRuntime.h>
+#include <android_runtime/android_graphics_GraphicBuffer.h>
#include <binder/Parcel.h>
@@ -266,7 +266,7 @@
// External helpers
// ----------------------------------------------------------------------------
-sp<GraphicBuffer> graphicBufferForJavaObject(JNIEnv* env, jobject obj) {
+sp<GraphicBuffer> android_graphics_GraphicBuffer_getNativeGraphicsBuffer(JNIEnv* env, jobject obj) {
if (obj) {
jlong nativeObject = env->GetLongField(obj, gGraphicBufferClassInfo.mNativeObject);
GraphicBufferWrapper* wrapper = (GraphicBufferWrapper*) nativeObject;
@@ -278,7 +278,9 @@
return NULL;
}
-jobject createJavaGraphicBuffer(JNIEnv* env, const sp<GraphicBuffer>& buffer) {
+jobject android_graphics_GraphicBuffer_createFromAHardwareBuffer(JNIEnv* env,
+ AHardwareBuffer* hardwareBuffer) {
+ GraphicBuffer* buffer = GraphicBuffer::fromAHardwareBuffer(hardwareBuffer);
GraphicBufferWrapper* wrapper = new GraphicBufferWrapper(buffer);
jobject obj = env->NewObject(gGraphicBufferClassInfo.mClass,
gGraphicBufferClassInfo.mConstructorMethodID, buffer->getWidth(), buffer->getHeight(),
diff --git a/core/jni/android_hardware_HardwareBuffer.cpp b/core/jni/android_hardware_HardwareBuffer.cpp
index 706a2b8..e78e08e 100644
--- a/core/jni/android_hardware_HardwareBuffer.cpp
+++ b/core/jni/android_hardware_HardwareBuffer.cpp
@@ -20,9 +20,9 @@
#include <nativehelper/JNIHelp.h>
#include "android_os_Parcel.h"
-#include "android/graphics/GraphicBuffer.h"
#include <android/hardware_buffer.h>
+#include <android_runtime/android_graphics_GraphicBuffer.h>
#include <android_runtime/android_hardware_HardwareBuffer.h>
#include <android_runtime/AndroidRuntime.h>
#include <android_runtime/Log.h>
@@ -97,7 +97,8 @@
}
static jlong android_hardware_HardwareBuffer_createFromGraphicBuffer(JNIEnv* env, jobject clazz, jobject graphicBuffer) {
- sp<GraphicBuffer> buffer(graphicBufferForJavaObject(env, graphicBuffer));
+ sp<GraphicBuffer> buffer(android_graphics_GraphicBuffer_getNativeGraphicsBuffer(env,
+ graphicBuffer));
GraphicBufferWrapper* wrapper = new GraphicBufferWrapper(buffer);
return reinterpret_cast<jlong>(wrapper);
}
diff --git a/core/jni/android_view_RenderNode.cpp b/core/jni/android_view_RenderNode.cpp
index 9450bc9..222a873 100644
--- a/core/jni/android_view_RenderNode.cpp
+++ b/core/jni/android_view_RenderNode.cpp
@@ -16,9 +16,6 @@
#define LOG_TAG "OpenGLRenderer"
#define ATRACE_TAG ATRACE_TAG_VIEW
-#ifdef __ANDROID__ // Layoutlib does not support EGL
-#include <EGL/egl.h>
-#endif
#include "jni.h"
#include "GraphicsJNI.h"
#include <nativehelper/JNIHelp.h>
diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp
index 8eb9c9a..d65e252 100644
--- a/core/jni/android_view_Surface.cpp
+++ b/core/jni/android_view_Surface.cpp
@@ -21,12 +21,12 @@
#include "jni.h"
#include <nativehelper/JNIHelp.h>
#include "android_os_Parcel.h"
-#include "android/graphics/GraphicBuffer.h"
#include "android/graphics/GraphicsJNI.h"
#include "core_jni_helpers.h"
-#include <android_runtime/android_view_Surface.h>
+#include <android_runtime/android_graphics_GraphicBuffer.h>
#include <android_runtime/android_graphics_SurfaceTexture.h>
+#include <android_runtime/android_view_Surface.h>
#include <android_runtime/Log.h>
#include <binder/Parcel.h>
@@ -35,6 +35,7 @@
#include <gui/view/Surface.h>
#include <gui/SurfaceControl.h>
+#include <ui/GraphicBuffer.h>
#include <ui/Rect.h>
#include <ui/Region.h>
@@ -432,8 +433,9 @@
static jint nativeAttachAndQueueBufferWithColorSpace(JNIEnv *env, jclass clazz, jlong nativeObject,
jobject graphicBuffer, jint colorSpaceId) {
Surface* surface = reinterpret_cast<Surface*>(nativeObject);
- sp<GraphicBuffer> bp = graphicBufferForJavaObject(env, graphicBuffer);
- int err = Surface::attachAndQueueBufferWithDataspace(surface, bp,
+ sp<GraphicBuffer> gb(android_graphics_GraphicBuffer_getNativeGraphicsBuffer(env,
+ graphicBuffer));
+ int err = Surface::attachAndQueueBufferWithDataspace(surface, gb,
fromNamedColorSpaceValueToDataspace(colorSpaceId));
return err;
}
diff --git a/core/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp
index b0443a8..dd3a4d0 100644
--- a/core/jni/android_view_ThreadedRenderer.cpp
+++ b/core/jni/android_view_ThreadedRenderer.cpp
@@ -520,14 +520,13 @@
// Continue I guess?
}
- SkColorType ct = uirenderer::PixelFormatToColorType(buffer->getPixelFormat());
sk_sp<SkColorSpace> cs = uirenderer::DataSpaceToColorSpace(bufferItem.mDataSpace);
if (cs == nullptr) {
// nullptr is treated as SRGB in Skia, thus explicitly use SRGB in order to make sure
// the returned bitmap has a color space.
cs = SkColorSpace::MakeSRGB();
}
- sk_sp<Bitmap> bitmap = Bitmap::createFrom(buffer, ct, cs);
+ sk_sp<Bitmap> bitmap = Bitmap::createFrom(buffer->toAHardwareBuffer(), cs);
return bitmap::createBitmap(env, bitmap.release(),
android::bitmap::kBitmapCreateFlag_Premultiplied);
}
diff --git a/core/jni/android/graphics/GraphicBuffer.h b/core/jni/include/android_runtime/android_graphics_GraphicBuffer.h
similarity index 69%
rename from core/jni/android/graphics/GraphicBuffer.h
rename to core/jni/include/android_runtime/android_graphics_GraphicBuffer.h
index 0d72669..5f15faa 100644
--- a/core/jni/android/graphics/GraphicBuffer.h
+++ b/core/jni/include/android_runtime/android_graphics_GraphicBuffer.h
@@ -14,16 +14,19 @@
* limitations under the License.
*/
-#include <ui/GraphicBuffer.h>
+#include <android/hardware_buffer.h>
#include "jni.h"
namespace android {
+class GraphicBuffer;
+
// This function does not perform any type checking, the specified
// object must be an instance of android.view.GraphicBuffer
-extern sp<GraphicBuffer> graphicBufferForJavaObject(JNIEnv* env, jobject obj);
+sp<GraphicBuffer> android_graphics_GraphicBuffer_getNativeGraphicsBuffer(JNIEnv* env, jobject obj);
-jobject createJavaGraphicBuffer(JNIEnv* env, const sp<GraphicBuffer>& buffer);
+extern jobject android_graphics_GraphicBuffer_createFromAHardwareBuffer(JNIEnv* env,
+ AHardwareBuffer* buffer);
}
diff --git a/core/proto/android/server/activitymanagerservice.proto b/core/proto/android/server/activitymanagerservice.proto
index 7fb6f98..a1ff9b9 100644
--- a/core/proto/android/server/activitymanagerservice.proto
+++ b/core/proto/android/server/activitymanagerservice.proto
@@ -261,6 +261,8 @@
// The dirty the pages that have been swapped out, proportional.
int32 dirty_swap_pss_kb = 9;
}
+ // The rss set size for the heap.
+ optional int32 total_rss_kb = 10;
}
message HeapInfo {
option (.android.msg_privacy).dest = DEST_AUTOMATIC;
@@ -294,6 +296,12 @@
int32 total_swap_pss = 8;
int32 total_swap_kb = 9;
}
+ optional int32 java_heap_rss_kb = 10;
+ optional int32 native_heap_rss_kb = 11;
+ optional int32 code_rss_kb = 12;
+ optional int32 stack_rss_kb = 13;
+ optional int32 graphics_rss_kb = 14;
+ optional int32 unknown_rss_kb = 15;
}
optional AppSummary app_summary = 9;
}
@@ -359,10 +367,16 @@
optional int32 id = 3;
optional bool is_proc = 4;
optional bool has_activities = 5;
- optional int64 pss_kb = 6;
+ oneof ss_kb {
+ int64 pss_kb = 6;
+ int64 rss_kb = 9;
+ }
optional int64 swap_pss_kb = 7;
repeated MemItem sub_items = 8;
}
+ repeated MemItem total_rss_by_process = 29;
+ repeated MemItem total_rss_by_oom_adjustment = 30;
+ repeated MemItem total_rss_by_category = 31;
repeated MemItem total_pss_by_process = 5;
repeated MemItem total_pss_by_oom_adjustment = 6;
repeated MemItem total_pss_by_category = 7;
@@ -414,6 +428,8 @@
optional bool is_low_ram_device = 27;
optional bool is_high_end_gfx = 28;
+
+ // Next Tag: 32
}
message StickyBroadcastProto {
diff --git a/core/proto/android/server/alarmmanagerservice.proto b/core/proto/android/server/alarmmanagerservice.proto
index 490f729..b008fa9 100644
--- a/core/proto/android/server/alarmmanagerservice.proto
+++ b/core/proto/android/server/alarmmanagerservice.proto
@@ -20,7 +20,7 @@
import "frameworks/base/core/proto/android/app/pendingintent.proto";
import "frameworks/base/core/proto/android/internal/locallog.proto";
import "frameworks/base/core/proto/android/os/worksource.proto";
-import "frameworks/base/core/proto/android/server/forceappstandbytracker.proto";
+import "frameworks/base/core/proto/android/server/appstatetracker.proto";
import "frameworks/base/core/proto/android/privacy.proto";
package com.android.server;
@@ -38,8 +38,8 @@
// Current settings
optional ConstantsProto settings = 5;
- // Dump from ForceAppStandbyTracker.
- optional ForceAppStandbyTrackerProto force_app_standby_tracker = 6;
+ // Dump from AppStateTracker.
+ optional AppStateTrackerProto app_state_tracker = 6;
optional bool is_interactive = 7;
// Only valid if is_interactive is false.
diff --git a/core/proto/android/server/forceappstandbytracker.proto b/core/proto/android/server/appstatetracker.proto
similarity index 91%
rename from core/proto/android/server/forceappstandbytracker.proto
rename to core/proto/android/server/appstatetracker.proto
index 89424bc..51e8845 100644
--- a/core/proto/android/server/forceappstandbytracker.proto
+++ b/core/proto/android/server/appstatetracker.proto
@@ -23,12 +23,15 @@
option java_multiple_files = true;
-// Dump from com.android.server.ForceAppStandbyTracker.
+// Dump from com.android.server.AppStateTracker.
//
-// Next ID: 13
-message ForceAppStandbyTrackerProto {
+// Next ID: 14
+message AppStateTrackerProto {
option (.android.msg_privacy).dest = DEST_AUTOMATIC;
+ // True if the forced app standby feature is enabled in settings.
+ optional bool forced_app_standby_feature_enabled = 13;
+
// Whether all apps are forced standby or not.
optional bool force_all_apps_standby = 1;
diff --git a/core/proto/android/server/jobscheduler.proto b/core/proto/android/server/jobscheduler.proto
index 5d4be55..aac144c 100644
--- a/core/proto/android/server/jobscheduler.proto
+++ b/core/proto/android/server/jobscheduler.proto
@@ -28,8 +28,9 @@
import "frameworks/base/core/proto/android/net/networkrequest.proto";
import "frameworks/base/core/proto/android/os/bundle.proto";
import "frameworks/base/core/proto/android/os/persistablebundle.proto";
-import "frameworks/base/core/proto/android/server/forceappstandbytracker.proto";
+import "frameworks/base/core/proto/android/server/appstatetracker.proto";
import "frameworks/base/core/proto/android/server/job/enums.proto";
+import "frameworks/base/core/proto/android/server/statlogger.proto";
import "frameworks/base/core/proto/android/privacy.proto";
// Next tag: 21
@@ -53,18 +54,22 @@
optional JobStatusShortInfoProto info = 1;
optional JobStatusDumpProto dump = 2;
+ optional bool is_job_ready_to_be_executed = 10;
// A job is ready to be executed if:
- // is_job_ready && is_user_started && !is_job_pending &&
+ // is_job_ready && are_users_started && !is_job_thermal_constrained && !is_job_pending &&
// !is_job_currently_active && !is_uid_backing_up &&
- // is_component_present.
+ // is_component_usable.
optional bool is_job_ready = 3;
- optional bool is_user_started = 4;
+ optional bool are_users_started = 4;
+ optional bool is_job_thermal_constrained = 11;
optional bool is_job_pending = 5;
optional bool is_job_currently_active = 6;
optional bool is_uid_backing_up = 7;
- optional bool is_component_present = 8;
+ optional bool is_component_usable = 8;
reserved 9; // last_run_heartbeat
+
+ // Next tag: 12
}
repeated RegisteredJob registered_jobs = 3;
@@ -95,7 +100,7 @@
optional JobStatusDumpProto dump = 2;
optional sint32 evaluated_priority = 3;
// How long this job has been pending.
- optional int64 enqueued_duration_ms = 4;
+ optional int64 pending_duration_ms = 4;
}
repeated PendingJob pending_jobs = 9;
@@ -123,7 +128,7 @@
optional sint32 evaluated_priority = 5;
optional int64 time_since_made_active_ms = 6;
- // How long this job has been pending.
+ // How long this job was pending before it became active.
optional int64 pending_duration_ms = 7;
}
oneof job {
@@ -144,6 +149,8 @@
// Dump from JobConcurrencyManager.
optional JobConcurrencyManagerProto concurrency_manager = 20;
+
+ optional JobStorePersistStatsProto persist_stats = 21;
}
// A com.android.server.job.JobSchedulerService.Constants object.
@@ -347,7 +354,7 @@
message BackgroundJobsController {
option (.android.msg_privacy).dest = DEST_AUTOMATIC;
- optional com.android.server.ForceAppStandbyTrackerProto force_app_standby_tracker = 1;
+ optional com.android.server.AppStateTrackerProto app_state_tracker = 1;
message TrackedJob {
option (.android.msg_privacy).dest = DEST_AUTOMATIC;
@@ -386,7 +393,7 @@
message ConnectivityController {
option (.android.msg_privacy).dest = DEST_AUTOMATIC;
- optional bool is_connected = 1;
+ reserved 1; // is_connected
message TrackedJob {
option (.android.msg_privacy).dest = DEST_AUTOMATIC;
@@ -396,6 +403,12 @@
optional .android.net.NetworkRequestProto required_network = 3;
}
repeated TrackedJob tracked_jobs = 2;
+
+ // List of the UIDs that ConnectivityController has requested that NetworkPolicyManager
+ // grant an exception to in the app standby chain.
+ repeated int32 requested_standby_exception_uids = 3;
+
+ repeated .android.net.NetworkProto available_networks = 4;
}
message ContentObserverController {
option (.android.msg_privacy).dest = DEST_AUTOMATIC;
@@ -480,6 +493,31 @@
optional int32 source_uid = 2;
}
repeated TrackedJob tracked_jobs = 2;
+
+ message IdlenessTracker {
+ option (.android.msg_privacy).dest = DEST_AUTOMATIC;
+
+ message CarIdlenessTracker {
+ option (.android.msg_privacy).dest = DEST_AUTOMATIC;
+
+ optional bool is_idle = 1;
+ optional bool is_garage_mode_on = 2;
+ }
+
+ message DeviceIdlenessTracker {
+ option (.android.msg_privacy).dest = DEST_AUTOMATIC;
+
+ optional bool is_idle = 1;
+ optional bool is_screen_on = 2;
+ optional bool is_dock_idle = 3;
+ }
+
+ oneof active_tracker {
+ DeviceIdlenessTracker device_idleness_tracker = 1;
+ CarIdlenessTracker car_idleness_tracker = 2;
+ }
+ }
+ optional IdlenessTracker idleness_tracker = 3;
}
message QuotaController {
option (.android.msg_privacy).dest = DEST_AUTOMATIC;
@@ -623,6 +661,17 @@
optional AlarmListener in_quota_alarm_listener = 5;
}
repeated PackageStats package_stats = 5;
+
+ // Set of package names for each UID.
+ message UidPackageMapping {
+ option (.android.msg_privacy).dest = DEST_AUTOMATIC;
+
+ optional int32 uid = 1;
+ repeated string package_names = 2;
+ }
+ repeated UidPackageMapping uid_to_package_cache = 7;
+
+ // Next tag: 8
}
message StorageController {
option (.android.msg_privacy).dest = DEST_AUTOMATIC;
@@ -937,10 +986,15 @@
optional sint64 time_until_earliest_runtime_ms = 19;
// Can be negative if the latest runtime deadline has passed.
optional sint64 time_until_latest_runtime_ms = 20;
+ // The original latest runtime value, in the elapsed realtime timebase. Valid only for periodic
+ // jobs.
+ optional uint64 original_latest_runtime_elapsed = 30;
optional int32 num_failures = 21;
+ // Last time a job finished successfully for a periodic job, in currentTimeMillis time.
optional int64 last_successful_run_time = 22;
+ // Last time a job finished unsuccessfully, in currentTimeMillis time.
optional int64 last_failed_run_time = 23;
optional int64 internal_flags = 24;
@@ -953,7 +1007,7 @@
// was no attempt.
optional int64 time_since_first_force_batch_attempt_ms = 29;
- // Next tag: 30
+ // Next tag: 31
}
// Dump from com.android.server.job.JobConcurrencyManager.
@@ -962,9 +1016,9 @@
option (.android.msg_privacy).dest = DEST_AUTOMATIC;
// Whether the device is interactive (== screen on) now or not.
- optional bool current_interactive = 1;
- // Similar to current_interactive, screen on or not, but it takes into account the off timeout.
- optional bool effective_interactive = 2;
+ optional bool current_interactive_state = 1;
+ // Similar to current_interactive_state, screen on or not, but it takes into account the off timeout.
+ optional bool effective_interactive_state = 2;
// How many milliseconds have passed since the last screen on. (i.e. 1000 == 1 sec ago)
optional int64 time_since_last_screen_on_ms = 3;
// How many milliseconds have passed since the last screen off. (i.e. 1000 == 1 sec ago)
@@ -973,6 +1027,8 @@
optional JobCountTrackerProto job_count_tracker = 5;
// Current memory trim level.
optional int32 memory_trim_level = 6;
+ // Performance stats.
+ optional StatLoggerProto stats = 7;
}
// Dump from com.android.server.job.JobConcurrencyManager.JobCountTracker.
@@ -997,4 +1053,23 @@
optional int32 num_pending_fg_jobs = 6;
// Number of pending background jobs.
optional int32 num_pending_bg_jobs = 7;
+
+ optional int32 num_actual_max_fg_jobs = 8;
+ optional int32 num_actual_max_bg_jobs = 9;
+
+ optional int32 num_reserved_for_bg = 10;
+
+ optional int32 num_starting_fg_jobs = 11;
+ optional int32 num_starting_bg_jobs = 12;
+}
+
+message JobStorePersistStatsProto {
+ message Stats {
+ optional int32 num_total_jobs = 1;
+ optional int32 num_system_server_jobs = 2;
+ optional int32 num_system_sync_manager_jobs = 3;
+ }
+
+ optional Stats first_load = 1;
+ optional Stats last_save = 2;
}
diff --git a/core/proto/android/server/statlogger.proto b/core/proto/android/server/statlogger.proto
index 8593da8..c995599 100644
--- a/core/proto/android/server/statlogger.proto
+++ b/core/proto/android/server/statlogger.proto
@@ -34,6 +34,9 @@
optional string label = 2;
optional int32 count = 3;
optional int64 total_duration_micros = 4;
+ optional int32 max_calls_per_second = 5;
+ optional int64 max_duration_per_second_micros = 6;
+ optional int64 max_duration_stats_micros = 7;
}
repeated Event events = 1;
diff --git a/core/proto/android/service/graphicsstats.proto b/core/proto/android/service/graphicsstats.proto
index 11f0467..557075c 100644
--- a/core/proto/android/service/graphicsstats.proto
+++ b/core/proto/android/service/graphicsstats.proto
@@ -51,6 +51,9 @@
// The frame time histogram for the package.
repeated GraphicsStatsHistogramBucketProto histogram = 6;
+
+ // The gpu frame time histogram for the package
+ repeated GraphicsStatsHistogramBucketProto gpu_histogram = 7;
}
message GraphicsStatsJankSummaryProto {
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 4d6e7da..fa4e085 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -3483,6 +3483,9 @@
<!-- True if home app should be pinned via Pinner Service -->
<bool name="config_pinnerHomeApp">false</bool>
+ <!-- True if assistant app should be pinned via Pinner Service -->
+ <bool name="config_pinnerAssistantApp">false</bool>
+
<!-- List of files pinned by the Pinner Service with the apex boot image b/119800099 -->
<string-array translatable="false" name="config_apexBootImagePinnerServiceFiles">
</string-array>
@@ -4267,6 +4270,10 @@
(default 2MB) -->
<integer name="config_notificationStripRemoteViewSizeBytes">2000000</integer>
+ <!-- Contains a blacklist of apps that should not get pre-installed carrier app permission
+ grants, even if the UICC claims that the app should be privileged. See b/138150105 -->
+ <string-array name="config_restrictedPreinstalledCarrierApps" translatable="false"/>
+
<!-- Sharesheet: define a max number of targets per application for new shortcuts-based direct share introduced in Q -->
<integer name="config_maxShortcutTargetsPerApp">3</integer>
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index 6653879..609659b 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -748,6 +748,8 @@
<!-- Line spacing modifier for the message field of the harmful app dialog -->
<item name="harmful_app_message_line_spacing_modifier" type="dimen">1.22</item>
+ <dimen name="seekbar_thumb_exclusion_max_size">48dp</dimen>
+
<!-- chooser (sharesheet) spacing -->
<dimen name="chooser_corner_radius">8dp</dimen>
<dimen name="chooser_row_text_option_translate">25dp</dimen>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 036d959..2067735 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2927,6 +2927,7 @@
<public type="attr" name="enforceStatusBarContrast" id="0x01010604" />
<public type="attr" name="enforceNavigationBarContrast" id="0x01010605" />
<public type="attr" name="identifier" id="0x01010606" />
+ <public type="attr" name="forceQueryable" id="0x01010608" />
<!-- @hide @SystemApi -->
<public type="drawable" name="ic_info" id="0x010800b4" />
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 40f20ab..d1d7bf5 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -370,7 +370,7 @@
<!-- If MMS discovers there isn't much space left on the device, it will show a toast with this message. [CHAR LIMIT=TOAST] -->
<string name="low_memory" product="watch">Watch storage is full. Delete some files to free space.</string>
<!-- If MMS discovers there isn't much space left on the device, it will show a toast with this message. [CHAR LIMIT=TOAST] -->
- <string name="low_memory" product="tv">TV storage is full. Delete some files to free space.</string>
+ <string name="low_memory" product="tv">Android TV device storage is full. Delete some files to free space.</string>
<!-- If MMS discovers there isn't much space left on the device, it will show a toast with this message. [CHAR LIMIT=TOAST] -->
<string name="low_memory" product="default">Phone storage is full. Delete some files to free space.</string>
@@ -430,7 +430,7 @@
<!-- Title for the Phone Options dialog to lock the screen, turn off the phone etc. -->
<string name="power_dialog" product="tablet">Tablet options</string>
<!-- Title for the Phone Options dialog to lock the screen, turn off the phone etc. -->
- <string name="power_dialog" product="tv">TV options</string>
+ <string name="power_dialog" product="tv">Android TV options</string>
<!-- Title for the Phone Options dialog to lock the screen, turn off the phone etc. -->
<string name="power_dialog" product="default">Phone options</string>
<!-- Button to turn on silent mode, within the Phone Options dialog -->
@@ -468,7 +468,7 @@
<string name="shutdown_confirm" product="tablet">Your tablet will shut down.</string>
<!-- Shutdown Confirmation Dialog. When the user chooses to power off the TV, there will
be a confirmation dialog. This is the message. -->
- <string name="shutdown_confirm" product="tv">Your TV will shut down.</string>
+ <string name="shutdown_confirm" product="tv">Your Android TV device will shut down.</string>
<!-- Shutdown Confirmation Dialog. When the user chooses to power off the watch, there will
be a confirmation dialog. This is the message. -->
<string name="shutdown_confirm" product="watch">Your watch will shut down.</string>
@@ -505,7 +505,7 @@
<!-- Title of the Global Actions Dialog -->
<string name="global_actions" product="tablet">Tablet options</string>
<!-- Title of the Global Actions Dialog -->
- <string name="global_actions" product="tv">TV options</string>
+ <string name="global_actions" product="tv">Android TV options</string>
<!-- Title of the Global Actions Dialog -->
<string name="global_actions" product="default">Phone options</string>
@@ -916,7 +916,7 @@
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permdesc_readSms" product="tablet">This app can read all SMS (text) messages stored on your tablet.</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
- <string name="permdesc_readSms" product="tv">This app can read all SMS (text) messages stored on your TV.</string>
+ <string name="permdesc_readSms" product="tv">This app can read all SMS (text) messages stored on your Android TV device.</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permdesc_readSms" product="default">This app can read all SMS (text) messages stored on your phone.</string>
@@ -979,7 +979,7 @@
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permdesc_persistentActivity" product="tablet">Allows the app to make parts of itself persistent in memory. This can limit memory available to other apps slowing down the tablet.</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
- <string name="permdesc_persistentActivity" product="tv">Allows the app to make parts of itself persistent in memory. This can limit memory available to other apps slowing down the TV.</string>
+ <string name="permdesc_persistentActivity" product="tv">Allows the app to make parts of itself persistent in memory. This can limit memory available to other apps slowing down your Android TV device.</string>
<string name="permdesc_persistentActivity" product="default">Allows the app to make parts of itself persistent in memory. This can limit memory available to other apps slowing down the phone.</string>
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
@@ -1009,8 +1009,8 @@
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permdesc_receiveBootCompleted" product="tv">Allows the app to
have itself started as soon as the system has finished booting.
- This can make it take longer to start the TV and allow the
- app to slow down the overall tablet by always running.</string>
+ This can make it take longer to start your Android TV device and allow the
+ app to slow down the overall device by always running.</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permdesc_receiveBootCompleted" product="default">Allows the app to
have itself started as soon as the system has finished booting.
@@ -1027,7 +1027,7 @@
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permdesc_broadcastSticky" product="tv">Allows the app to
send sticky broadcasts, which remain after the broadcast ends. Excessive use
- may make the TV slow or unstable by causing it to use too much memory.
+ may make your Android TV device slow or unstable by causing it to use too much memory.
</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permdesc_broadcastSticky" product="default">Allows the app to
@@ -1046,7 +1046,7 @@
knowledge.</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permdesc_readContacts" product="tv">Allows the app to read
- data about your contacts stored on your TV, including the frequency
+ data about your contacts stored on your Android TV device, including the frequency
with which you\'ve called, emailed, or communicated in other ways with
specific individuals. This permission allows apps to save your contact
data, and malicious apps may share contact data without your
@@ -1069,7 +1069,7 @@
data.</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permdesc_writeContacts" product="tv">Allows the app to
- modify the data about your contacts stored on your TV, including the
+ modify the data about your contacts stored on your Android TV device, including the
frequency with which you\'ve called, emailed, or communicated in other ways
with specific contacts. This permission allows apps to delete contact
data.</string>
@@ -1091,7 +1091,7 @@
<string name="permdesc_writeCallLog" product="tablet">Allows the app to modify your tablet\'s call log, including data about incoming and outgoing calls.
Malicious apps may use this to erase or modify your call log.</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
- <string name="permdesc_writeCallLog" product="tv">Allows the app to modify your TV\'s call log, including data about incoming and outgoing calls.
+ <string name="permdesc_writeCallLog" product="tv">Allows the app to modify your Android TV device\'s call log, including data about incoming and outgoing calls.
Malicious apps may use this to erase or modify your call log.</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permdesc_writeCallLog" product="default">Allows the app to modify your phone\'s call log, including data about incoming and outgoing calls.
@@ -1109,7 +1109,7 @@
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permdesc_readCalendar" product="tablet">This app can read all calendar events stored on your tablet and share or save your calendar data.</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
- <string name="permdesc_readCalendar" product="tv">This app can read all calendar events stored on your TV and share or save your calendar data.</string>
+ <string name="permdesc_readCalendar" product="tv">This app can read all calendar events stored on your Android TV device and share or save your calendar data.</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permdesc_readCalendar" product="default">This app can read all calendar events stored on your phone and share or save your calendar data.</string>
@@ -1118,7 +1118,7 @@
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permdesc_writeCalendar" product="tablet">This app can add, remove, or change calendar events on your tablet. This app can send messages that may appear to come from calendar owners, or change events without notifying their owners.</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
- <string name="permdesc_writeCalendar" product="tv">This app can add, remove, or change calendar events on your TV. This app can send messages that may appear to come from calendar owners, or change events without notifying their owners.</string>
+ <string name="permdesc_writeCalendar" product="tv">This app can add, remove, or change calendar events on your Android TV device. This app can send messages that may appear to come from calendar owners, or change events without notifying their owners.</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permdesc_writeCalendar" product="default">This app can add, remove, or change calendar events on your phone. This app can send messages that may appear to come from calendar owners, or change events without notifying their owners.</string>
@@ -1139,7 +1139,7 @@
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permdesc_accessCoarseLocation" product="tablet">This app can get your location based on network sources such as cell towers and Wi-Fi networks, but only when when the app is in the foreground. These location services must be turned on and available on your tablet for the app to be able to use them.</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
- <string name="permdesc_accessCoarseLocation" product="tv">This app can get your location based on network sources such as cell towers and Wi-Fi networks, but only when when the app is in the foreground. These location services must be turned on and available on your TV for the app to be able to use them.</string>
+ <string name="permdesc_accessCoarseLocation" product="tv">This app can get your location based on network sources such as cell towers and Wi-Fi networks, but only when when the app is in the foreground. These location services must be turned on and available on your Android TV device for the app to be able to use them.</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permdesc_accessCoarseLocation" product="default">This app can get your location based on network sources such as cell towers and Wi-Fi networks, but only when the app is in the foreground. These location services must be turned on and available on your phone for the app to be able to use them.</string>
@@ -1236,13 +1236,13 @@
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permlab_wakeLock" product="tablet">prevent tablet from sleeping</string>
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
- <string name="permlab_wakeLock" product="tv">prevent TV from sleeping</string>
+ <string name="permlab_wakeLock" product="tv">prevent your Android TV device from sleeping</string>
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permlab_wakeLock" product="default">prevent phone from sleeping</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permdesc_wakeLock" product="tablet">Allows the app to prevent the tablet from going to sleep.</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
- <string name="permdesc_wakeLock" product="tv">Allows the app to prevent the TV from going to sleep.</string>
+ <string name="permdesc_wakeLock" product="tv">Allows the app to prevent your Android TV device from going to sleep.</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permdesc_wakeLock" product="default">Allows the app to prevent the phone from going to sleep.</string>
@@ -1251,7 +1251,7 @@
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permdesc_transmitIr" product="tablet">Allows the app to use the tablet\'s infrared transmitter.</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
- <string name="permdesc_transmitIr" product="tv">Allows the app to use the TV\'s infrared transmitter.</string>
+ <string name="permdesc_transmitIr" product="tv">Allows the app to use your Android TV device\'s infrared transmitter.</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permdesc_transmitIr" product="default">Allows the app to use the phone\'s infrared transmitter.</string>
@@ -1270,7 +1270,7 @@
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permdesc_setTimeZone" product="tablet">Allows the app to change the tablet\'s time zone.</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
- <string name="permdesc_setTimeZone" product="tv">Allows the app to change the TV\'s time zone.</string>
+ <string name="permdesc_setTimeZone" product="tv">Allows the app to change your Android TV device\'s time zone.</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permdesc_setTimeZone" product="default">Allows the app to change the phone\'s time zone.</string>
@@ -1282,7 +1282,7 @@
created by applications you have installed.</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permdesc_getAccounts" product="tv">Allows the app to get
- the list of accounts known by the TV. This may include any accounts
+ the list of accounts known by your Android TV device. This may include any accounts
created by applications you have installed.</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permdesc_getAccounts" product="default">Allows the app to get
@@ -1337,7 +1337,7 @@
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permdesc_changeWifiMulticastState" product="tv">Allows the app to receive
packets sent to all devices on a Wi-Fi network using multicast addresses,
- not just your TV. It uses more power than the non-multicast mode.</string>
+ not just your Android TV device. It uses more power than the non-multicast mode.</string>
<string name="permdesc_changeWifiMulticastState" product="default">Allows the app to receive
packets sent to all devices on a Wi-Fi network using multicast addresses,
not just your phone. It uses more power than the non-multicast mode.</string>
@@ -1350,7 +1350,7 @@
devices.</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permdesc_bluetoothAdmin" product="tv">Allows the app to
- configure the local Bluetooth TV, and to discover and pair with remote
+ configure Bluetooth on your Android TV device, and to discover and pair with remote
devices.</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permdesc_bluetoothAdmin" product="default">Allows the app to configure
@@ -1365,7 +1365,7 @@
<string name="permdesc_changeWimaxState" product="tablet">Allows the app to
connect the tablet to and disconnect the tablet from WiMAX networks.</string>
<string name="permdesc_changeWimaxState" product="tv">Allows the app to
- connect the TV to and disconnect the TV from WiMAX networks.</string>
+ connect your Android TV device to and disconnect your Android TV device from WiMAX networks.</string>
<string name="permdesc_changeWimaxState" product="default">Allows the app to
connect the phone to and disconnect the phone from WiMAX networks.</string>
@@ -1377,7 +1377,7 @@
connections with paired devices.</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permdesc_bluetooth" product="tv">Allows the app to view the
- configuration of Bluetooth on the TV, and to make and accept
+ configuration of Bluetooth on your Android TV device, and to make and accept
connections with paired devices.</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permdesc_bluetooth" product="default">Allows the app to view the
@@ -1753,8 +1753,8 @@
typed when unlocking the screen, and lock the tablet or erase all the tablet\'s
data if too many incorrect passwords are typed.</string>
<!-- Description of policy access to watch user login attempts -->
- <string name="policydesc_watchLogin" product="TV">Monitor the number of incorrect passwords
- typed when unlocking the screen, and lock the TV or erase all the TV\'s
+ <string name="policydesc_watchLogin" product="tv">Monitor the number of incorrect passwords
+ typed when unlocking the screen, and lock your Android TV device or erase all your Android TV device\'s
data if too many incorrect passwords are typed.</string>
<!-- Description of policy access to watch user login attempts -->
<string name="policydesc_watchLogin" product="default">Monitor the number of incorrect passwords
@@ -1763,8 +1763,8 @@
<string name="policydesc_watchLogin_secondaryUser" product="tablet">Monitor the number of incorrect passwords
typed when unlocking the screen, and lock the tablet or erase all this user\'s data
if too many incorrect passwords are typed.</string>
- <string name="policydesc_watchLogin_secondaryUser" product="TV">Monitor the number of incorrect passwords
- typed when unlocking the screen, and lock the TV or erase all this user\'s data
+ <string name="policydesc_watchLogin_secondaryUser" product="tv">Monitor the number of incorrect passwords
+ typed when unlocking the screen, and lock your Android TV device or erase all this user\'s data
if too many incorrect passwords are typed.</string>
<string name="policydesc_watchLogin_secondaryUser" product="default">Monitor the number of incorrect passwords
typed when unlocking the screen, and lock the phone or erase all this user\'s data
@@ -1782,7 +1782,7 @@
<!-- Description of policy access to wipe the user's data -->
<string name="policydesc_wipeData" product="tablet">Erase the tablet\'s data without warning by performing a factory data reset.</string>
<!-- Description of policy access to wipe the user's data -->
- <string name="policydesc_wipeData" product="tv">Erase the TV\'s data without warning by performing a factory data reset.</string>
+ <string name="policydesc_wipeData" product="tv">Erase your Android TV device\'s data without warning by performing a factory data reset.</string>
<!-- Description of policy access to wipe the user's data -->
<string name="policydesc_wipeData" product="default">Erase the phone\'s data without warning by performing a factory data reset.</string>
<!-- Title of policy access to wipe secondary user's data -->
@@ -1790,7 +1790,7 @@
<!-- Description of policy access to wipe the user's data -->
<string name="policydesc_wipeData_secondaryUser" product="tablet">Erase this user\'s data on this tablet without warning.</string>
<!-- Description of policy access to wipe the user's data -->
- <string name="policydesc_wipeData_secondaryUser" product="tv">Erase this user\'s data on this TV without warning.</string>
+ <string name="policydesc_wipeData_secondaryUser" product="tv">Erase this user\'s data on this Android TV device without warning.</string>
<!-- Description of policy access to wipe the user's data -->
<string name="policydesc_wipeData_secondaryUser" product="default">Erase this user\'s data on this phone without warning.</string>
<!-- Title of policy access to set global proxy -->
@@ -2103,7 +2103,7 @@
<!-- Shown in the lock screen when there is no SIM card. -->
<string name="lockscreen_missing_sim_message" product="tablet">No SIM card in tablet.</string>
<!-- Shown in the lock screen when there is no SIM card. -->
- <string name="lockscreen_missing_sim_message" product="tv">No SIM card in TV.</string>
+ <string name="lockscreen_missing_sim_message" product="tv">No SIM card in your Android TV device.</string>
<!-- Shown in the lock screen when there is no SIM card. -->
<string name="lockscreen_missing_sim_message" product="default">No SIM card in phone.</string>
<!-- Shown in the lock screen to ask the user to insert a SIM card. -->
@@ -2188,7 +2188,7 @@
<string name="lockscreen_failed_attempts_almost_glogin" product="tv">
You have incorrectly drawn your unlock pattern <xliff:g id="number">%1$d</xliff:g> times.
After <xliff:g id="number">%2$d</xliff:g> more unsuccessful attempts,
- you will be asked to unlock your TV using your Google signin.\n\n
+ you will be asked to unlock your Android TV device using your Google signin.\n\n
Try again in <xliff:g id="number">%3$d</xliff:g> seconds.
</string>
@@ -2212,9 +2212,9 @@
<!-- For the unlock screen, informational message shown in dialog when user is almost at the limit
where the device will be wiped. -->
<string name="lockscreen_failed_attempts_almost_at_wipe" product="tv">
- You have incorrectly attempted to unlock the TV <xliff:g id="number">%1$d</xliff:g> times.
+ You have incorrectly attempted to unlock your Android TV device <xliff:g id="number">%1$d</xliff:g> times.
After <xliff:g id="number">%2$d</xliff:g> more unsuccessful attempts,
- the TV will be reset to factory default and all user data will be lost.
+ your Android TV device will be reset to factory default and all user data will be lost.
</string>
<!-- For the unlock screen, informational message shown in dialog when user is almost at the limit
@@ -2235,8 +2235,8 @@
<!-- For the unlock screen, informational message shown in dialog when user has exceeded the
maximum attempts and the device will now be wiped -->
<string name="lockscreen_failed_attempts_now_wiping" product="tv">
- You have incorrectly attempted to unlock the TV <xliff:g id="number">%d</xliff:g> times.
- The TV will now be reset to factory default.
+ You have incorrectly attempted to unlock your Android TV device <xliff:g id="number">%d</xliff:g> times.
+ Your Android TV device will now be reset to factory default.
</string>
<!-- For the unlock screen, informational message shown in dialog when user has exceeded the
@@ -2603,7 +2603,7 @@
<!-- Description of an application permission, listed so the user can choose whether
they want to allow the application to do this. -->
<string name="permdesc_writeHistoryBookmarks" product="tv">Allows the
- app to modify the Browser\'s history or bookmarks stored on your TV.
+ app to modify the Browser\'s history or bookmarks stored on your Android TV device.
This may allow the app to erase or modify Browser data. Note: this
permission may note be enforced by third-party browsers or other
applications with web browsing capabilities.</string>
@@ -3506,7 +3506,7 @@
<string name="wifi_p2p_show_pin_message">PIN: </string>
<string name="wifi_p2p_frequency_conflict_message" product="tablet">The tablet will temporarily disconnect from Wi-Fi while it\'s connected to <xliff:g id="device_name">%1$s</xliff:g></string>
- <string name="wifi_p2p_frequency_conflict_message" product="tv">The TV will temporarily disconnect from Wi-Fi while it\'s connected to <xliff:g id="device_name">%1$s</xliff:g></string>
+ <string name="wifi_p2p_frequency_conflict_message" product="tv">Your Android TV device will temporarily disconnect from Wi-Fi while it\'s connected to <xliff:g id="device_name">%1$s</xliff:g></string>
<string name="wifi_p2p_frequency_conflict_message" product="default">The phone will temporarily disconnect from Wi-Fi while it\'s connected to <xliff:g id="device_name">%1$s</xliff:g></string>
<!-- Name of the dialog that lets the user choose an accented character to insert -->
@@ -4404,9 +4404,9 @@
</string>
<!-- Message shown when user is almost at the limit of password attempts where the device will be wiped. -->
<string name="kg_failed_attempts_almost_at_wipe" product="tv">
- You have incorrectly attempted to unlock the TV <xliff:g id="number">%1$d</xliff:g> times.
+ You have incorrectly attempted to unlock your Android TV device <xliff:g id="number">%1$d</xliff:g> times.
After <xliff:g id="number">%2$d</xliff:g> more unsuccessful attempts,
- the TV will be reset to factory default and all user data will be lost.
+ your Android TV device will be reset to factory default and all user data will be lost.
</string>
<!-- Message shown when user is almost at the limit of password attempts where the device will be wiped. -->
<string name="kg_failed_attempts_almost_at_wipe" product="default">
@@ -4421,8 +4421,8 @@
</string>
<!-- Message shown in dialog when user has exceeded the maximum attempts and the device will now be wiped -->
<string name="kg_failed_attempts_now_wiping" product="tv">
- You have incorrectly attempted to unlock the TV <xliff:g id="number">%d</xliff:g> times.
- The TV will now be reset to factory default.
+ You have incorrectly attempted to unlock your Android TV device <xliff:g id="number">%d</xliff:g> times.
+ Your Android TV device will now be reset to factory default.
</string>
<!-- Message shown in dialog when user has exceeded the maximum attempts and the device will now be wiped -->
<string name="kg_failed_attempts_now_wiping" product="default">
@@ -4442,7 +4442,7 @@
<string name="kg_failed_attempts_almost_at_login" product="tv">
You have incorrectly drawn your unlock pattern <xliff:g id="number">%1$d</xliff:g> times.
After <xliff:g id="number">%2$d</xliff:g> more unsuccessful attempts,
- you will be asked to unlock your TV using an email account.\n\n
+ you will be asked to unlock your Android TV device using an email account.\n\n
Try again in <xliff:g id="number">%3$d</xliff:g> seconds.
</string>
<!-- Message shown in dialog when user is almost at the limit where they will be
@@ -5299,6 +5299,13 @@
<!-- Application name displayed in notifications [CHAR LIMIT=60] -->
<string name="notification_app_name_settings">Settings</string>
+ <!-- Title of the overlay warning the user to interact with the device or it will go into standby. [CHAR LIMIT=25] -->
+ <string name="standby_warning_title">Standby</string>
+ <!-- Message of the overlay warning the user to interact with the device or it will go into standby. [CHAR LIMIT=NONE] -->
+ <string name="standby_warning_message" product="tv">The Android TV device will soon turn off; press a button to keep it on.</string>
+ <!-- Message of the overlay warning the user to interact with the device or it will go into standby. [CHAR LIMIT=NONE] -->
+ <string name="standby_warning_message" product="default">The device will soon turn off; press to keep it on.</string>
+
<!-- Active Permission - accessibility support -->
<!-- Content description of the camera icon in the notification. [CHAR LIMIT=NONE] -->
<string name="notification_appops_camera_active">Camera</string>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 4094bf4..f7ae453 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -3118,6 +3118,7 @@
<java-symbol type="array" name="config_defaultPinnerServiceFiles" />
<java-symbol type="bool" name="config_pinnerCameraApp" />
<java-symbol type="bool" name="config_pinnerHomeApp" />
+ <java-symbol type="bool" name="config_pinnerAssistantApp" />
<java-symbol type="array" name="config_apexBootImagePinnerServiceFiles" />
<java-symbol type="string" name="config_doubleTouchGestureEnableFile" />
@@ -3825,6 +3826,7 @@
<java-symbol type="color" name="chooser_gradient_highlight" />
<java-symbol type="drawable" name="chooser_direct_share_label_placeholder" />
<java-symbol type="dimen" name="chooser_direct_share_label_placeholder_max_width" />
+ <java-symbol type="dimen" name="seekbar_thumb_exclusion_max_size" />
<java-symbol type="layout" name="chooser_az_label_row" />
<java-symbol type="string" name="chooser_all_apps_button_label" />
<java-symbol type="anim" name="resolver_launch_anim" />
@@ -3834,6 +3836,7 @@
<java-symbol type="string" name="config_defaultSupervisionProfileOwnerComponent" />
<java-symbol type="bool" name="config_inflateSignalStrength" />
+ <java-symbol type="array" name="config_restrictedPreinstalledCarrierApps" />
<java-symbol type="drawable" name="android_logotype" />
<java-symbol type="layout" name="platlogo_layout" />
diff --git a/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/hal2/StartProgramListUpdatesFanoutTest.java b/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/hal2/StartProgramListUpdatesFanoutTest.java
index 6e65df1..3d9a1d9 100644
--- a/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/hal2/StartProgramListUpdatesFanoutTest.java
+++ b/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/hal2/StartProgramListUpdatesFanoutTest.java
@@ -250,6 +250,29 @@
verify(mHalTunerSessionMock).stopProgramListUpdates();
}
+ @Test
+ public void testNullAidlFilter() throws RemoteException {
+ openAidlClients(1);
+ mTunerSessions[0].startProgramListUpdates(null);
+ verify(mHalTunerSessionMock, times(1)).startProgramListUpdates(any());
+
+ // Verify the AIDL client receives all types of updates (e.g. a new program, an update to
+ // that program, and a category).
+ updateHalProgramInfo(true, Arrays.asList(mAmFmInfo, mRdsInfo), null);
+ verifyAidlClientReceivedChunk(mAidlTunerCallbackMocks[0], true, Arrays.asList(
+ mAmFmInfo, mRdsInfo), null);
+ updateHalProgramInfo(false, Arrays.asList(mModifiedAmFmInfo), null);
+ verifyAidlClientReceivedChunk(mAidlTunerCallbackMocks[0], false,
+ Arrays.asList(mModifiedAmFmInfo), null);
+ updateHalProgramInfo(false, Arrays.asList(mDabEnsembleInfo), null);
+ verifyAidlClientReceivedChunk(mAidlTunerCallbackMocks[0], false,
+ Arrays.asList(mDabEnsembleInfo), null);
+
+ // Verify closing the AIDL session also stops HAL updates.
+ mTunerSessions[0].close();
+ verify(mHalTunerSessionMock).stopProgramListUpdates();
+ }
+
private void openAidlClients(int numClients) throws RemoteException {
mAidlTunerCallbackMocks = new android.hardware.radio.ITunerCallback[numClients];
mTunerSessions = new TunerSession[numClients];
diff --git a/core/tests/coretests/src/android/content/ContentProviderOperationTest.java b/core/tests/coretests/src/android/content/ContentProviderOperationTest.java
index b142761..b1ce33a 100644
--- a/core/tests/coretests/src/android/content/ContentProviderOperationTest.java
+++ b/core/tests/coretests/src/android/content/ContentProviderOperationTest.java
@@ -26,11 +26,6 @@
import junit.framework.TestCase;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Field;
-import java.lang.reflect.InvocationTargetException;
-import java.util.HashMap;
-import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
@@ -39,11 +34,6 @@
private final static Uri sTestUri1 = Uri.parse("content://authority/blah");
private final static ContentValues sTestValues1;
- private final static Class<ContentProviderOperation.Builder> CLASS_BUILDER =
- ContentProviderOperation.Builder.class;
- private final static Class<ContentProviderOperation> CLASS_OPERATION =
- ContentProviderOperation.class;
-
static {
sTestValues1 = new ContentValues();
sTestValues1.put("a", 1);
@@ -279,221 +269,6 @@
assertEquals("a,103,101,b,102", TextUtils.join(",", s2));
}
- public void testParcelingOperation() throws NoSuchFieldException, IllegalAccessException,
- NoSuchMethodException, InvocationTargetException, InstantiationException {
- Parcel parcel = Parcel.obtain();
- ContentProviderOperation op1;
- ContentProviderOperation op2;
-
- HashMap<Integer, Integer> selArgsBackRef = new HashMap<Integer, Integer>();
- selArgsBackRef.put(1, 2);
- selArgsBackRef.put(3, 4);
-
- ContentValues values = new ContentValues();
- values.put("v1", "val1");
- values.put("v2", "43");
-
- ContentValues valuesBackRef = new ContentValues();
- values.put("v3", "val3");
- values.put("v4", "44");
-
- try {
- ContentProviderOperation.Builder builder = ContentProviderOperation.newInsert(
- Uri.parse("content://goo/bar"));
-
- builderSetExpectedCount(builder, 42);
- builderSetSelection(builder, "selection");
- builderSetSelectionArgs(builder, new String[]{"a", "b"});
- builderSetSelectionArgsBackReferences(builder, selArgsBackRef);
- builderSetValues(builder, values);
- builderSetValuesBackReferences(builder, valuesBackRef);
-
- op1 = newOperationFromBuilder(builder);
- op1.writeToParcel(parcel, 0);
- parcel.setDataPosition(0);
- op2 = ContentProviderOperation.CREATOR.createFromParcel(parcel);
-
- assertEquals(ContentProviderOperation.TYPE_INSERT, operationGetType(op2));
- assertEquals("content://goo/bar", operationGetUri(op2).toString());
- assertEquals(Integer.valueOf(42), operationGetExpectedCount(op2));
- assertEquals("selection", operationGetSelection(op2));
- assertEquals(2, operationGetSelectionArgs(op2).length);
- assertEquals("a", operationGetSelectionArgs(op2)[0]);
- assertEquals("b", operationGetSelectionArgs(op2)[1]);
- assertEquals(values, operationGetValues(op2));
- assertEquals(valuesBackRef, operationGetValuesBackReferences(op2));
- assertEquals(2, operationGetSelectionArgsBackReferences(op2).size());
- assertEquals(Integer.valueOf(2), operationGetSelectionArgsBackReferences(op2).get(1));
- assertEquals(Integer.valueOf(4), operationGetSelectionArgsBackReferences(op2).get(3));
- } finally {
- parcel.recycle();
- }
-
- try {
- ContentProviderOperation.Builder builder = ContentProviderOperation.newUpdate(
- Uri.parse("content://goo/bar"));
-
- builderSetSelectionArgsBackReferences(builder, selArgsBackRef);
-
- op1 = newOperationFromBuilder(builder);
- op1.writeToParcel(parcel, 0);
- parcel.setDataPosition(0);
- op2 = ContentProviderOperation.CREATOR.createFromParcel(parcel);
- assertEquals(ContentProviderOperation.TYPE_UPDATE, operationGetType(op2));
- assertEquals("content://goo/bar", operationGetUri(op2).toString());
- assertNull(operationGetExpectedCount(op2));
- assertNull(operationGetSelection(op2));
- assertNull(operationGetSelectionArgs(op2));
- assertNull(operationGetValues(op2));
- assertNull(operationGetValuesBackReferences(op2));
- assertEquals(2, operationGetSelectionArgsBackReferences(op2).size());
- assertEquals(Integer.valueOf(2), operationGetSelectionArgsBackReferences(op2).get(1));
- assertEquals(Integer.valueOf(4), operationGetSelectionArgsBackReferences(op2).get(3));
- } finally {
- parcel.recycle();
- }
-
- try {
- ContentProviderOperation.Builder builder = ContentProviderOperation.newDelete(
- Uri.parse("content://goo/bar"));
-
- op1 = newOperationFromBuilder(builder);
- op1.writeToParcel(parcel, 0);
- parcel.setDataPosition(0);
- op2 = ContentProviderOperation.CREATOR.createFromParcel(parcel);
- assertEquals(ContentProviderOperation.TYPE_DELETE, operationGetType(op2));
- assertEquals("content://goo/bar", operationGetUri(op2).toString());
- assertNull(operationGetExpectedCount(op2));
- assertNull(operationGetSelection(op2));
- assertNull(operationGetSelectionArgs(op2));
- assertNull(operationGetValues(op2));
- assertNull(operationGetValuesBackReferences(op2));
- assertNull(operationGetSelectionArgsBackReferences(op2));
- } finally {
- parcel.recycle();
- }
- }
-
- private static ContentProviderOperation newOperationFromBuilder(
- ContentProviderOperation.Builder builder)
- throws NoSuchMethodException, InstantiationException, IllegalAccessException,
- InvocationTargetException {
- final Constructor constructor = CLASS_OPERATION.getDeclaredConstructor(CLASS_BUILDER);
- constructor.setAccessible(true);
- return (ContentProviderOperation) constructor.newInstance(builder);
- }
-
- private void builderSetSelectionArgsBackReferences(
- ContentProviderOperation.Builder builder, HashMap<Integer, Integer> selArgsBackRef)
- throws NoSuchFieldException, IllegalAccessException {
- Field field;
- field = CLASS_BUILDER.getDeclaredField("mSelectionArgsBackReferences");
- field.setAccessible(true);
- field.set(builder, selArgsBackRef);
- }
-
- private void builderSetValuesBackReferences(
- ContentProviderOperation.Builder builder, ContentValues valuesBackReferences)
- throws NoSuchFieldException, IllegalAccessException {
- Field field;
- field = CLASS_BUILDER.getDeclaredField("mValuesBackReferences");
- field.setAccessible(true);
- field.set(builder, valuesBackReferences);
- }
-
- private void builderSetSelection(
- ContentProviderOperation.Builder builder, String selection)
- throws NoSuchFieldException, IllegalAccessException {
- Field field;
- field = CLASS_BUILDER.getDeclaredField("mSelection");
- field.setAccessible(true);
- field.set(builder, selection);
- }
-
- private void builderSetSelectionArgs(
- ContentProviderOperation.Builder builder, String[] selArgs)
- throws NoSuchFieldException, IllegalAccessException {
- Field field;
- field = CLASS_BUILDER.getDeclaredField("mSelectionArgs");
- field.setAccessible(true);
- field.set(builder, selArgs);
- }
-
- private void builderSetValues(
- ContentProviderOperation.Builder builder, ContentValues values)
- throws NoSuchFieldException, IllegalAccessException {
- Field field;
- field = CLASS_BUILDER.getDeclaredField("mValues");
- field.setAccessible(true);
- field.set(builder, values);
- }
-
- private void builderSetExpectedCount(
- ContentProviderOperation.Builder builder, Integer expectedCount)
- throws NoSuchFieldException, IllegalAccessException {
- Field field;
- field = CLASS_BUILDER.getDeclaredField("mExpectedCount");
- field.setAccessible(true);
- field.set(builder, expectedCount);
- }
-
- private int operationGetType(ContentProviderOperation operation)
- throws NoSuchFieldException, IllegalAccessException {
- final Field field = CLASS_OPERATION.getDeclaredField("mType");
- field.setAccessible(true);
- return field.getInt(operation);
- }
-
- private Uri operationGetUri(ContentProviderOperation operation)
- throws NoSuchFieldException, IllegalAccessException {
- final Field field = CLASS_OPERATION.getDeclaredField("mUri");
- field.setAccessible(true);
- return (Uri) field.get(operation);
- }
-
- private String operationGetSelection(ContentProviderOperation operation)
- throws NoSuchFieldException, IllegalAccessException {
- final Field field = CLASS_OPERATION.getDeclaredField("mSelection");
- field.setAccessible(true);
- return (String) field.get(operation);
- }
-
- private String[] operationGetSelectionArgs(ContentProviderOperation operation)
- throws NoSuchFieldException, IllegalAccessException {
- final Field field = CLASS_OPERATION.getDeclaredField("mSelectionArgs");
- field.setAccessible(true);
- return (String[]) field.get(operation);
- }
-
- private ContentValues operationGetValues(ContentProviderOperation operation)
- throws NoSuchFieldException, IllegalAccessException {
- final Field field = CLASS_OPERATION.getDeclaredField("mValues");
- field.setAccessible(true);
- return (ContentValues) field.get(operation);
- }
-
- private Integer operationGetExpectedCount(ContentProviderOperation operation)
- throws NoSuchFieldException, IllegalAccessException {
- final Field field = CLASS_OPERATION.getDeclaredField("mExpectedCount");
- field.setAccessible(true);
- return (Integer) field.get(operation);
- }
-
- private ContentValues operationGetValuesBackReferences(ContentProviderOperation operation)
- throws NoSuchFieldException, IllegalAccessException {
- final Field field = CLASS_OPERATION.getDeclaredField("mValuesBackReferences");
- field.setAccessible(true);
- return (ContentValues) field.get(operation);
- }
-
- private Map<Integer, Integer> operationGetSelectionArgsBackReferences(
- ContentProviderOperation operation)
- throws NoSuchFieldException, IllegalAccessException {
- final Field field = CLASS_OPERATION.getDeclaredField("mSelectionArgsBackReferences");
- field.setAccessible(true);
- return (Map<Integer, Integer>) field.get(operation);
- }
-
public void testParcelingResult() {
Parcel parcel = Parcel.obtain();
ContentProviderResult result1;
diff --git a/core/tests/coretests/src/android/content/pm/PackageParserTest.java b/core/tests/coretests/src/android/content/pm/PackageParserTest.java
index 58c43ac2..5c7f2af 100644
--- a/core/tests/coretests/src/android/content/pm/PackageParserTest.java
+++ b/core/tests/coretests/src/android/content/pm/PackageParserTest.java
@@ -428,6 +428,18 @@
"com.android.frameworks.coretests.install_complete_package_info.test_permission",
packageName, PermissionInfo.PROTECTION_NORMAL, p.permissions.get(0));
+ // Hidden "app details" activity is added to every package.
+ boolean foundAppDetailsActivity = false;
+ for (int i = 0; i < p.activities.size(); i++) {
+ if (p.activities.get(i).className.equals(
+ PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME)) {
+ foundAppDetailsActivity = true;
+ p.activities.remove(i);
+ break;
+ }
+ }
+ assertTrue("Did not find app details activity", foundAppDetailsActivity);
+
assertOneComponentOfEachType("com.android.frameworks.coretests.Test%s", p);
assertMetadata(p.mAppMetaData,
@@ -508,7 +520,12 @@
apexInfo.modulePath = apexFile.getPath();
apexInfo.versionCode = 191000070;
int flags = PackageManager.GET_META_DATA | PackageManager.GET_SIGNING_CERTIFICATES;
- PackageInfo pi = PackageParser.generatePackageInfoFromApex(apexInfo, flags);
+
+ PackageParser pp = new PackageParser();
+ Package p = pp.parsePackage(apexFile, flags, false);
+ PackageParser.collectCertificates(p, false);
+ PackageInfo pi = PackageParser.generatePackageInfo(p, apexInfo, flags);
+
assertEquals("com.google.android.tzdata", pi.applicationInfo.packageName);
assertTrue(pi.applicationInfo.enabled);
assertEquals(28, pi.applicationInfo.targetSdkVersion);
diff --git a/core/tests/coretests/src/android/os/ParcelNullabilityTest.java b/core/tests/coretests/src/android/os/ParcelNullabilityTest.java
index a6b296d..b4e180c 100644
--- a/core/tests/coretests/src/android/os/ParcelNullabilityTest.java
+++ b/core/tests/coretests/src/android/os/ParcelNullabilityTest.java
@@ -327,8 +327,8 @@
Parcel p = Parcel.obtain();
p.writeParcelableList(null, 0);
- List<Object> list = new ArrayList<>();
- throughBytes(p).readParcelableList(null, null);
+ List<Parcelable> list = new ArrayList<>();
+ throughBytes(p).readParcelableList(list, null);
assertTrue(list.isEmpty());
}
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index 89ba3df..bdbf368 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -35,6 +35,7 @@
import org.junit.runner.RunWith;
import java.lang.reflect.Field;
+import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
@@ -625,7 +626,6 @@
Settings.Secure.DIALER_DEFAULT_APPLICATION,
Settings.Secure.DISABLED_PRINT_SERVICES,
Settings.Secure.DISABLED_SYSTEM_INPUT_METHODS,
- Settings.Secure.DISPLAY_DENSITY_FORCED,
Settings.Secure.DOCKED_CLOCK_FACE,
Settings.Secure.DOZE_PULSE_ON_LONG_PRESS,
Settings.Secure.EMERGENCY_ASSISTANCE_APPLICATION,
@@ -742,9 +742,12 @@
@Test
public void secureSettingsBackedUpOrBlacklisted() {
+ HashSet<String> keys = new HashSet<String>();
+ Collections.addAll(keys, Settings.Secure.SETTINGS_TO_BACKUP);
+ Collections.addAll(keys, Settings.Secure.DEVICE_SPECIFIC_SETTINGS_TO_BACKUP);
checkSettingsBackedUpOrBlacklisted(
getCandidateSettings(Settings.Secure.class),
- newHashSet(Settings.Secure.SETTINGS_TO_BACKUP),
+ keys,
BACKUP_BLACKLISTED_SECURE_SETTINGS);
}
@@ -758,9 +761,9 @@
is(empty()));
assertThat(
- "blacklisted settings backed up",
- intersect(settingsToBackup, blacklist),
- is(empty()));
+ "blacklisted settings backed up",
+ intersect(settingsToBackup, blacklist),
+ is(empty()));
}
private static Set<String> getCandidateSettings(Class<? extends Settings.NameValueTable> clazz) {
diff --git a/core/tests/coretests/src/android/widget/AbsSeekBarTest.java b/core/tests/coretests/src/android/widget/AbsSeekBarTest.java
new file mode 100644
index 0000000..aec6096
--- /dev/null
+++ b/core/tests/coretests/src/android/widget/AbsSeekBarTest.java
@@ -0,0 +1,136 @@
+/*
+ * 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.widget;
+
+import static android.view.View.MeasureSpec.EXACTLY;
+import static android.view.View.MeasureSpec.makeMeasureSpec;
+
+import static org.hamcrest.Matchers.hasItem;
+import static org.hamcrest.Matchers.hasSize;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+
+import android.content.Context;
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.graphics.drawable.ShapeDrawable;
+import android.graphics.drawable.shapes.RectShape;
+import android.platform.test.annotations.Presubmit;
+import android.view.View;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Arrays;
+import java.util.List;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+@Presubmit
+public class AbsSeekBarTest {
+
+ private Context mContext;
+ private AbsSeekBar mBar;
+
+ @Before
+ public void setUp() throws Exception {
+ mContext = InstrumentationRegistry.getInstrumentation().getContext();
+ mBar = new SeekBar(mContext);
+ }
+
+ @Test
+ public void testExclusionForThumb_limitedTo48dp() {
+ mBar.setPadding(10, 10, 10, 10);
+ mBar.setThumb(newThumb(dpToPx(20)));
+ mBar.setMin(0);
+ mBar.setMax(100);
+ mBar.setProgress(50);
+ measureAndLayout(dpToPx(200), dpToPx(100));
+ List<Rect> exclusions = mBar.getSystemGestureExclusionRects();
+
+ assertEquals("exclusions should be size 1, but was " + exclusions, 1, exclusions.size());
+ assertEquals("exclusion should be centered on thumb",
+ center(mBar), center(exclusions.get(0)));
+ assertEquals("exclusion should be 48dp high", dpToPx(48), exclusions.get(0).height());
+ assertEquals("exclusion should be 48dp wide", dpToPx(48), exclusions.get(0).width());
+ }
+
+ @Test
+ public void testExclusionForThumb_limitedToHeight() {
+ mBar.setPadding(10, 10, 10, 10);
+ mBar.setThumb(newThumb(dpToPx(20)));
+ mBar.setMin(0);
+ mBar.setMax(100);
+ mBar.setProgress(50);
+ measureAndLayout(dpToPx(200), dpToPx(32));
+ List<Rect> exclusions = mBar.getSystemGestureExclusionRects();
+
+ assertEquals("exclusions should be size 1, but was " + exclusions, 1, exclusions.size());
+ assertEquals("exclusion should be centered on thumb",
+ center(mBar), center(exclusions.get(0)));
+ assertEquals("exclusion should be 32dp high", dpToPx(32), exclusions.get(0).height());
+ assertEquals("exclusion should be 32dp wide", dpToPx(32), exclusions.get(0).width());
+ }
+
+ @Test
+ public void testExclusionForThumb_passesThroughUserExclusions() {
+ mBar.setSystemGestureExclusionRects(Arrays.asList(new Rect(1, 2, 3, 4)));
+
+ mBar.setPadding(10, 10, 10, 10);
+ mBar.setThumb(newThumb(dpToPx(20)));
+ mBar.setMin(0);
+ mBar.setMax(100);
+ mBar.setProgress(50);
+ measureAndLayout(dpToPx(200), dpToPx(32));
+
+ assertThat(mBar.getSystemGestureExclusionRects(), hasItem(new Rect(1, 2, 3, 4)));
+ assertThat(mBar.getSystemGestureExclusionRects(), hasSize(2));
+
+ mBar.setSystemGestureExclusionRects(Arrays.asList(new Rect(3, 4, 5, 6)));
+ assertThat(mBar.getSystemGestureExclusionRects(), hasItem(new Rect(3, 4, 5, 6)));
+ assertThat(mBar.getSystemGestureExclusionRects(), hasSize(2));
+ }
+
+ private Point center(Rect rect) {
+ return new Point(rect.centerX(), rect.centerY());
+ }
+
+ private Point center(View view) {
+ return center(new Rect(view.getLeft(), view.getTop(), view.getRight(), view.getBottom()));
+ }
+
+ private ShapeDrawable newThumb(int size) {
+ final ShapeDrawable thumb = new ShapeDrawable(new RectShape());
+ thumb.setIntrinsicWidth(size);
+ thumb.setIntrinsicHeight(size);
+ return thumb;
+ }
+
+ private void measureAndLayout(int wPx, int hPx) {
+ mBar.measure(makeMeasureSpec(wPx, EXACTLY), makeMeasureSpec(hPx, EXACTLY));
+ mBar.layout(0, 0, wPx, hPx);
+ }
+
+ private int dpToPx(int dp) {
+ return (int) (mContext.getResources().getDisplayMetrics().density * dp);
+ }
+}
diff --git a/graphics/java/android/graphics/FontFamily.java b/graphics/java/android/graphics/FontFamily.java
index 5af0da8..5ad93f4 100644
--- a/graphics/java/android/graphics/FontFamily.java
+++ b/graphics/java/android/graphics/FontFamily.java
@@ -21,7 +21,6 @@
import android.content.res.AssetManager;
import android.graphics.fonts.FontVariationAxis;
import android.text.TextUtils;
-import android.util.Log;
import dalvik.annotation.optimization.CriticalNative;
@@ -145,7 +144,6 @@
}
return nAddFont(mBuilderPtr, fontBuffer, ttcIndex, weight, italic);
} catch (IOException e) {
- Log.e(TAG, "Error mapping font file " + path);
return false;
}
}
diff --git a/graphics/java/android/graphics/fonts/SystemFonts.java b/graphics/java/android/graphics/fonts/SystemFonts.java
index 4a9cf14..95a8417 100644
--- a/graphics/java/android/graphics/fonts/SystemFonts.java
+++ b/graphics/java/android/graphics/fonts/SystemFonts.java
@@ -105,7 +105,6 @@
final long fontSize = fileChannel.size();
return fileChannel.map(FileChannel.MapMode.READ_ONLY, 0, fontSize);
} catch (IOException e) {
- Log.e(TAG, "Error mapping font file " + fullPath);
return null;
}
}
diff --git a/keystore/java/android/security/AttestedKeyPair.java b/keystore/java/android/security/AttestedKeyPair.java
index c6bff5c..2debfee 100644
--- a/keystore/java/android/security/AttestedKeyPair.java
+++ b/keystore/java/android/security/AttestedKeyPair.java
@@ -16,6 +16,9 @@
package android.security;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
import java.security.KeyPair;
import java.security.cert.Certificate;
import java.util.ArrayList;
@@ -36,9 +39,12 @@
private final Certificate[] mAttestationRecord;
/**
- * @hide Only created by the platform, no need to expose as public API.
+ * Public constructor for creating a new instance (useful for testing).
+ *
+ * @param keyPair the key pair associated with the attestation record.
+ * @param attestationRecord attestation record for the provided key pair.
*/
- public AttestedKeyPair(KeyPair keyPair, Certificate[] attestationRecord) {
+ public AttestedKeyPair(@Nullable KeyPair keyPair, @Nullable Certificate[] attestationRecord) {
mKeyPair = keyPair;
mAttestationRecord = attestationRecord;
}
@@ -47,7 +53,7 @@
* Returns the generated key pair associated with the attestation record
* in this instance.
*/
- public KeyPair getKeyPair() {
+ public @Nullable KeyPair getKeyPair() {
return mKeyPair;
}
@@ -66,7 +72,7 @@
* and <a href="https://developer.android.com/training/articles/security-key-attestation.html">
* Key Attestation</a> for the format of the attestation record inside the certificate.
*/
- public List<Certificate> getAttestationRecord() {
+ public @NonNull List<Certificate> getAttestationRecord() {
if (mAttestationRecord == null) {
return new ArrayList();
}
diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp
index 0d837f2..ae90f11 100644
--- a/libs/hwui/Android.bp
+++ b/libs/hwui/Android.bp
@@ -88,6 +88,7 @@
"libvulkan",
"libui",
"libgui",
+ "libnativewindow",
"libprotobuf-cpp-lite",
"libft2",
"libandroidfw",
diff --git a/libs/hwui/FrameInfo.cpp b/libs/hwui/FrameInfo.cpp
index 71cc9a8..0698775 100644
--- a/libs/hwui/FrameInfo.cpp
+++ b/libs/hwui/FrameInfo.cpp
@@ -37,13 +37,14 @@
"FrameCompleted",
"DequeueBufferDuration",
"QueueBufferDuration",
+ "GpuCompleted",
};
static_assert((sizeof(FrameInfoNames) / sizeof(FrameInfoNames[0])) ==
static_cast<int>(FrameInfoIndex::NumIndexes),
"size mismatch: FrameInfoNames doesn't match the enum!");
-static_assert(static_cast<int>(FrameInfoIndex::NumIndexes) == 16,
+static_assert(static_cast<int>(FrameInfoIndex::NumIndexes) == 17,
"Must update value in FrameMetrics.java#FRAME_STATS_COUNT (and here)");
void FrameInfo::importUiThreadInfo(int64_t* info) {
diff --git a/libs/hwui/FrameInfo.h b/libs/hwui/FrameInfo.h
index b75192f..51674fb 100644
--- a/libs/hwui/FrameInfo.h
+++ b/libs/hwui/FrameInfo.h
@@ -51,6 +51,8 @@
DequeueBufferDuration,
QueueBufferDuration,
+ GpuCompleted,
+
// Must be the last value!
// Also must be kept in sync with FrameMetrics.java#FRAME_STATS_COUNT
NumIndexes
@@ -143,6 +145,13 @@
return duration(FrameInfoIndex::IntendedVsync, FrameInfoIndex::FrameCompleted);
}
+ inline int64_t gpuDrawTime() const {
+ // GPU start time is approximated to the moment before swapBuffer is invoked.
+ // We could add an EGLSyncKHR fence at the beginning of the frame, but that is an overhead.
+ int64_t endTime = get(FrameInfoIndex::GpuCompleted);
+ return endTime > 0 ? endTime - get(FrameInfoIndex::SwapBuffers) : -1;
+ }
+
inline int64_t& set(FrameInfoIndex index) { return mFrameInfo[static_cast<int>(index)]; }
inline int64_t get(FrameInfoIndex index) const {
diff --git a/libs/hwui/HardwareBitmapUploader.cpp b/libs/hwui/HardwareBitmapUploader.cpp
index 9bb6031..40bff88 100644
--- a/libs/hwui/HardwareBitmapUploader.cpp
+++ b/libs/hwui/HardwareBitmapUploader.cpp
@@ -403,8 +403,9 @@
if (!sUploader->uploadHardwareBitmap(bitmap, format, buffer)) {
return nullptr;
}
- return Bitmap::createFrom(buffer, bitmap.colorType(), bitmap.refColorSpace(),
- bitmap.alphaType(), Bitmap::computePalette(bitmap));
+ return Bitmap::createFrom(buffer->toAHardwareBuffer(), bitmap.colorType(),
+ bitmap.refColorSpace(), bitmap.alphaType(),
+ Bitmap::computePalette(bitmap));
}
void HardwareBitmapUploader::initialize() {
diff --git a/libs/hwui/JankTracker.cpp b/libs/hwui/JankTracker.cpp
index 53c5ad8..eae3584 100644
--- a/libs/hwui/JankTracker.cpp
+++ b/libs/hwui/JankTracker.cpp
@@ -232,5 +232,13 @@
: FrameInfoIndex::IntendedVsync;
}
+void JankTracker::finishGpuDraw(const FrameInfo& frame) {
+ int64_t totalGPUDrawTime = frame.gpuDrawTime();
+ if (totalGPUDrawTime >= 0) {
+ mData->reportGPUFrame(totalGPUDrawTime);
+ (*mGlobalData)->reportGPUFrame(totalGPUDrawTime);
+ }
+}
+
} /* namespace uirenderer */
} /* namespace android */
diff --git a/libs/hwui/JankTracker.h b/libs/hwui/JankTracker.h
index 110211e..08059268 100644
--- a/libs/hwui/JankTracker.h
+++ b/libs/hwui/JankTracker.h
@@ -58,6 +58,7 @@
FrameInfo* startFrame() { return &mFrames.next(); }
void finishFrame(const FrameInfo& frame);
+ void finishGpuDraw(const FrameInfo& frame);
void dumpStats(int fd) { dumpData(fd, &mDescription, mData.get()); }
void dumpFrames(int fd);
diff --git a/libs/hwui/ProfileData.cpp b/libs/hwui/ProfileData.cpp
index c7f9232..7921662 100644
--- a/libs/hwui/ProfileData.cpp
+++ b/libs/hwui/ProfileData.cpp
@@ -98,6 +98,10 @@
if (mStatStartTime > other.mStatStartTime || mStatStartTime == 0) {
mStatStartTime = other.mStatStartTime;
}
+ for (size_t i = 0; i < other.mGPUFrameCounts.size(); i++) {
+ mGPUFrameCounts[i] >>= divider;
+ mGPUFrameCounts[i] += other.mGPUFrameCounts[i];
+ }
}
void ProfileData::dump(int fd) const {
@@ -117,6 +121,14 @@
histogramForEach([fd](HistogramEntry entry) {
dprintf(fd, " %ums=%u", entry.renderTimeMs, entry.frameCount);
});
+ dprintf(fd, "\n50th gpu percentile: %ums", findGPUPercentile(50));
+ dprintf(fd, "\n90th gpu percentile: %ums", findGPUPercentile(90));
+ dprintf(fd, "\n95th gpu percentile: %ums", findGPUPercentile(95));
+ dprintf(fd, "\n99th gpu percentile: %ums", findGPUPercentile(99));
+ dprintf(fd, "\nGPU HISTOGRAM:");
+ histogramGPUForEach([fd](HistogramEntry entry) {
+ dprintf(fd, " %ums=%u", entry.renderTimeMs, entry.frameCount);
+ });
}
uint32_t ProfileData::findPercentile(int percentile) const {
@@ -140,6 +152,7 @@
void ProfileData::reset() {
mJankTypeCounts.fill(0);
mFrameCounts.fill(0);
+ mGPUFrameCounts.fill(0);
mSlowFrameCounts.fill(0);
mTotalFrameCount = 0;
mJankFrameCount = 0;
@@ -167,5 +180,40 @@
}
}
+uint32_t ProfileData::findGPUPercentile(int percentile) const {
+ uint32_t totalGPUFrameCount = 0; // this is usually mTotalFrameCount - 3.
+ for (int i = mGPUFrameCounts.size() - 1; i >= 0; i--) {
+ totalGPUFrameCount += mGPUFrameCounts[i];
+ }
+ int pos = percentile * totalGPUFrameCount / 100;
+ int remaining = totalGPUFrameCount - pos;
+ for (int i = mGPUFrameCounts.size() - 1; i >= 0; i--) {
+ remaining -= mGPUFrameCounts[i];
+ if (remaining <= 0) {
+ return GPUFrameTimeForFrameCountIndex(i);
+ }
+ }
+ return 0;
+}
+
+uint32_t ProfileData::GPUFrameTimeForFrameCountIndex(uint32_t index) {
+ return index != 25 ? index + 1 : 4950;
+}
+
+void ProfileData::reportGPUFrame(int64_t duration) {
+ uint32_t index = static_cast<uint32_t>(ns2ms(duration));
+ if (index > 25) {
+ index = 25;
+ }
+
+ mGPUFrameCounts[index]++;
+}
+
+void ProfileData::histogramGPUForEach(const std::function<void(HistogramEntry)>& callback) const {
+ for (size_t i = 0; i < mGPUFrameCounts.size(); i++) {
+ callback(HistogramEntry{GPUFrameTimeForFrameCountIndex(i), mGPUFrameCounts[i]});
+ }
+}
+
} /* namespace uirenderer */
} /* namespace android */
\ No newline at end of file
diff --git a/libs/hwui/ProfileData.h b/libs/hwui/ProfileData.h
index 564920b..ccbffc6 100644
--- a/libs/hwui/ProfileData.h
+++ b/libs/hwui/ProfileData.h
@@ -54,8 +54,10 @@
void mergeWith(const ProfileData& other);
void dump(int fd) const;
uint32_t findPercentile(int percentile) const;
+ uint32_t findGPUPercentile(int percentile) const;
void reportFrame(int64_t duration);
+ void reportGPUFrame(int64_t duration);
void reportJank() { mJankFrameCount++; }
void reportJankType(JankType type) { mJankTypeCounts[static_cast<int>(type)]++; }
@@ -69,15 +71,21 @@
uint32_t frameCount;
};
void histogramForEach(const std::function<void(HistogramEntry)>& callback) const;
+ void histogramGPUForEach(const std::function<void(HistogramEntry)>& callback) const;
constexpr static int HistogramSize() {
return std::tuple_size<decltype(ProfileData::mFrameCounts)>::value +
std::tuple_size<decltype(ProfileData::mSlowFrameCounts)>::value;
}
+ constexpr static int GPUHistogramSize() {
+ return std::tuple_size<decltype(ProfileData::mGPUFrameCounts)>::value;
+ }
+
// Visible for testing
static uint32_t frameTimeForFrameCountIndex(uint32_t index);
static uint32_t frameTimeForSlowFrameCountIndex(uint32_t index);
+ static uint32_t GPUFrameTimeForFrameCountIndex(uint32_t index);
private:
// Open our guts up to unit tests
@@ -88,6 +96,9 @@
std::array<uint32_t, 57> mFrameCounts;
// Holds a histogram of frame times in 50ms increments from 150ms to 5s
std::array<uint16_t, 97> mSlowFrameCounts;
+ // Holds a histogram of GPU draw times in 1ms increments. Frames longer than 25ms are placed in
+ // last bucket.
+ std::array<uint32_t, 26> mGPUFrameCounts;
uint32_t mTotalFrameCount;
uint32_t mJankFrameCount;
diff --git a/libs/hwui/VectorDrawable.cpp b/libs/hwui/VectorDrawable.cpp
index f91d178..61403aa 100644
--- a/libs/hwui/VectorDrawable.cpp
+++ b/libs/hwui/VectorDrawable.cpp
@@ -16,19 +16,24 @@
#include "VectorDrawable.h"
+#include <math.h>
+#include <string.h>
#include <utils/Log.h>
-#include "hwui/Paint.h"
+
#include "PathParser.h"
#include "SkColorFilter.h"
#include "SkImageInfo.h"
#include "SkShader.h"
+#include "hwui/Paint.h"
+
+#ifdef __ANDROID__
+#include "renderthread/RenderThread.h"
+#endif
+
#include "utils/Macros.h"
#include "utils/TraceUtils.h"
#include "utils/VectorDrawableUtils.h"
-#include <math.h>
-#include <string.h>
-
namespace android {
namespace uirenderer {
namespace VectorDrawable {
@@ -472,7 +477,7 @@
mStagingProperties.getBounds().bottom(), &paint);
}
-void Tree::getPaintFor(SkPaint* outPaint, const TreeProperties &prop) const {
+void Tree::getPaintFor(SkPaint* outPaint, const TreeProperties& prop) const {
// HWUI always draws VD with bilinear filtering.
outPaint->setFilterQuality(kLow_SkFilterQuality);
if (prop.getColorFilter() != nullptr) {
@@ -492,7 +497,7 @@
}
void Tree::updateCache(sp<skiapipeline::VectorDrawableAtlas>& atlas, GrContext* context) {
-#ifdef __ANDROID__ // Layoutlib does not support hardware acceleration
+#ifdef __ANDROID__ // Layoutlib does not support hardware acceleration
SkRect dst;
sk_sp<SkSurface> surface = mCache.getSurface(&dst);
bool canReuseSurface = surface && dst.width() >= mProperties.getScaledWidth() &&
@@ -533,7 +538,7 @@
sk_sp<SkSurface> Tree::Cache::getSurface(SkRect* bounds) {
sk_sp<SkSurface> surface;
-#ifdef __ANDROID__ // Layoutlib does not support hardware acceleration
+#ifdef __ANDROID__ // Layoutlib does not support hardware acceleration
sp<skiapipeline::VectorDrawableAtlas> atlas = mAtlas.promote();
if (atlas.get() && mAtlasKey != INVALID_ATLAS_KEY) {
auto atlasEntry = atlas->getEntry(mAtlasKey);
@@ -547,13 +552,28 @@
}
void Tree::Cache::clear() {
-#ifdef __ANDROID__ // Layoutlib does not support hardware acceleration
- sp<skiapipeline::VectorDrawableAtlas> lockAtlas = mAtlas.promote();
- if (lockAtlas.get()) {
- lockAtlas->releaseEntry(mAtlasKey);
+#ifdef __ANDROID__ // Layoutlib does not support hardware acceleration
+ if (mAtlasKey != INVALID_ATLAS_KEY) {
+ if (renderthread::RenderThread::isCurrent()) {
+ sp<skiapipeline::VectorDrawableAtlas> lockAtlas = mAtlas.promote();
+ if (lockAtlas.get()) {
+ lockAtlas->releaseEntry(mAtlasKey);
+ }
+ } else {
+ // VectorDrawableAtlas can be accessed only on RenderThread.
+ // Use by-copy capture of the current Cache variables, because "this" may not be valid
+ // by the time the lambda is evaluated on RenderThread.
+ renderthread::RenderThread::getInstance().queue().post(
+ [atlas = mAtlas, atlasKey = mAtlasKey]() {
+ sp<skiapipeline::VectorDrawableAtlas> lockAtlas = atlas.promote();
+ if (lockAtlas.get()) {
+ lockAtlas->releaseEntry(atlasKey);
+ }
+ });
+ }
+ mAtlasKey = INVALID_ATLAS_KEY;
}
mAtlas = nullptr;
- mAtlasKey = INVALID_ATLAS_KEY;
#endif
}
diff --git a/libs/hwui/hwui/Bitmap.cpp b/libs/hwui/hwui/Bitmap.cpp
index 4c2f0ad..a1be5b7 100644
--- a/libs/hwui/hwui/Bitmap.cpp
+++ b/libs/hwui/hwui/Bitmap.cpp
@@ -148,12 +148,26 @@
#ifdef __ANDROID__ // Layoutlib does not support hardware acceleration
-sk_sp<Bitmap> Bitmap::createFrom(sp<GraphicBuffer> graphicBuffer, SkColorType colorType,
+sk_sp<Bitmap> Bitmap::createFrom(AHardwareBuffer* hardwareBuffer, sk_sp<SkColorSpace> colorSpace,
+ BitmapPalette palette) {
+ AHardwareBuffer_Desc bufferDesc;
+ AHardwareBuffer_describe(hardwareBuffer, &bufferDesc);
+ SkImageInfo info = uirenderer::BufferDescriptionToImageInfo(bufferDesc, colorSpace);
+
+ const size_t rowBytes = info.bytesPerPixel() * bufferDesc.stride;
+ return sk_sp<Bitmap>(new Bitmap(hardwareBuffer, info, rowBytes, palette));
+}
+
+sk_sp<Bitmap> Bitmap::createFrom(AHardwareBuffer* hardwareBuffer, SkColorType colorType,
sk_sp<SkColorSpace> colorSpace, SkAlphaType alphaType,
BitmapPalette palette) {
- SkImageInfo info = SkImageInfo::Make(graphicBuffer->getWidth(), graphicBuffer->getHeight(),
+ AHardwareBuffer_Desc bufferDesc;
+ AHardwareBuffer_describe(hardwareBuffer, &bufferDesc);
+ SkImageInfo info = SkImageInfo::Make(bufferDesc.width, bufferDesc.height,
colorType, alphaType, colorSpace);
- return sk_sp<Bitmap>(new Bitmap(graphicBuffer.get(), info, palette));
+
+ const size_t rowBytes = info.bytesPerPixel() * bufferDesc.stride;
+ return sk_sp<Bitmap>(new Bitmap(hardwareBuffer, info, rowBytes, palette));
}
#endif
@@ -238,18 +252,17 @@
}
#ifdef __ANDROID__ // Layoutlib does not support hardware acceleration
-Bitmap::Bitmap(GraphicBuffer* buffer, const SkImageInfo& info, BitmapPalette palette)
- : SkPixelRef(info.width(), info.height(), nullptr,
- bytesPerPixel(buffer->getPixelFormat()) * buffer->getStride())
+Bitmap::Bitmap(AHardwareBuffer* buffer, const SkImageInfo& info, size_t rowBytes,
+ BitmapPalette palette)
+ : SkPixelRef(info.width(), info.height(), nullptr, rowBytes)
, mInfo(validateAlpha(info))
, mPixelStorageType(PixelStorageType::Hardware)
, mPalette(palette)
, mPaletteGenerationId(getGenerationID()) {
mPixelStorage.hardware.buffer = buffer;
- buffer->incStrong(buffer);
+ AHardwareBuffer_acquire(buffer);
setImmutable(); // HW bitmaps are always immutable
- mImage = SkImage::MakeFromAHardwareBuffer(reinterpret_cast<AHardwareBuffer*>(buffer),
- mInfo.alphaType(), mInfo.refColorSpace());
+ mImage = SkImage::MakeFromAHardwareBuffer(buffer, mInfo.alphaType(), mInfo.refColorSpace());
}
#endif
@@ -274,7 +287,7 @@
case PixelStorageType::Hardware:
#ifdef __ANDROID__ // Layoutlib does not support hardware acceleration
auto buffer = mPixelStorage.hardware.buffer;
- buffer->decStrong(buffer);
+ AHardwareBuffer_release(buffer);
mPixelStorage.hardware.buffer = nullptr;
#endif
break;
@@ -352,7 +365,7 @@
}
#ifdef __ANDROID__ // Layoutlib does not support hardware acceleration
-GraphicBuffer* Bitmap::graphicBuffer() {
+AHardwareBuffer* Bitmap::hardwareBuffer() {
if (isHardware()) {
return mPixelStorage.hardware.buffer;
}
diff --git a/libs/hwui/hwui/Bitmap.h b/libs/hwui/hwui/Bitmap.h
index c7e18d1..00733c6 100644
--- a/libs/hwui/hwui/Bitmap.h
+++ b/libs/hwui/hwui/Bitmap.h
@@ -24,7 +24,7 @@
#include <SkPixelRef.h>
#include <cutils/compiler.h>
#ifdef __ANDROID__ // Layoutlib does not support hardware acceleration
-#include <ui/GraphicBuffer.h>
+#include <android/hardware_buffer.h>
#endif
namespace android {
@@ -74,11 +74,15 @@
* memory that is provided as an input param.
*/
#ifdef __ANDROID__ // Layoutlib does not support hardware acceleration
- static sk_sp<Bitmap> createFrom(sp<GraphicBuffer> graphicBuffer,
+ static sk_sp<Bitmap> createFrom(AHardwareBuffer* hardwareBuffer,
+ sk_sp<SkColorSpace> colorSpace,
+ BitmapPalette palette = BitmapPalette::Unknown);
+
+ static sk_sp<Bitmap> createFrom(AHardwareBuffer* hardwareBuffer,
SkColorType colorType,
sk_sp<SkColorSpace> colorSpace,
- SkAlphaType alphaType = kPremul_SkAlphaType,
- BitmapPalette palette = BitmapPalette::Unknown);
+ SkAlphaType alphaType,
+ BitmapPalette palette);
#endif
static sk_sp<Bitmap> createFrom(const SkImageInfo& info, size_t rowBytes, int fd, void* addr,
size_t size, bool readOnly);
@@ -110,7 +114,7 @@
PixelStorageType pixelStorageType() const { return mPixelStorageType; }
#ifdef __ANDROID__ // Layoutlib does not support hardware acceleration
- GraphicBuffer* graphicBuffer();
+ AHardwareBuffer* hardwareBuffer();
#endif
/**
@@ -143,7 +147,8 @@
size_t rowBytes);
Bitmap(void* address, int fd, size_t mappedSize, const SkImageInfo& info, size_t rowBytes);
#ifdef __ANDROID__ // Layoutlib does not support hardware acceleration
- Bitmap(GraphicBuffer* buffer, const SkImageInfo& info, BitmapPalette palette);
+ Bitmap(AHardwareBuffer* buffer, const SkImageInfo& info, size_t rowBytes,
+ BitmapPalette palette);
#endif
virtual ~Bitmap();
@@ -175,7 +180,7 @@
} heap;
#ifdef __ANDROID__ // Layoutlib does not support hardware acceleration
struct {
- GraphicBuffer* buffer;
+ AHardwareBuffer* buffer;
} hardware;
#endif
} mPixelStorage;
diff --git a/libs/hwui/protos/graphicsstats.proto b/libs/hwui/protos/graphicsstats.proto
index 1226d44..0cd5c62 100644
--- a/libs/hwui/protos/graphicsstats.proto
+++ b/libs/hwui/protos/graphicsstats.proto
@@ -46,6 +46,9 @@
// The frame time histogram for the package
repeated GraphicsStatsHistogramBucketProto histogram = 6;
+
+ // The gpu frame time histogram for the package
+ repeated GraphicsStatsHistogramBucketProto gpu_histogram = 7;
}
message GraphicsStatsJankSummaryProto {
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index d19351b..88a0c6e 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -147,6 +147,7 @@
mNativeSurface = new ReliableSurface{std::move(surface)};
// TODO: Fix error handling & re-shorten timeout
mNativeSurface->setDequeueTimeout(4000_ms);
+ mNativeSurface->enableFrameTimestamps(true);
} else {
mNativeSurface = nullptr;
}
@@ -294,6 +295,7 @@
// just keep using the previous frame's structure instead
if (!wasSkipped(mCurrentFrameInfo)) {
mCurrentFrameInfo = mJankTracker.startFrame();
+ mLast4FrameInfos.next().first = mCurrentFrameInfo;
}
mCurrentFrameInfo->importUiThreadInfo(uiFrameInfo);
mCurrentFrameInfo->set(FrameInfoIndex::SyncQueued) = syncQueued;
@@ -445,7 +447,7 @@
mContentDrawBounds, mOpaque, mLightInfo, mRenderNodes,
&(profiler()));
- int64_t frameCompleteNr = mFrameCompleteCallbacks.size() ? getFrameNumber() : -1;
+ int64_t frameCompleteNr = getFrameNumber();
waitOnFences();
@@ -500,11 +502,13 @@
}
mCurrentFrameInfo->set(FrameInfoIndex::DequeueBufferDuration) = swap.dequeueDuration;
mCurrentFrameInfo->set(FrameInfoIndex::QueueBufferDuration) = swap.queueDuration;
+ mLast4FrameInfos[-1].second = frameCompleteNr;
mHaveNewSurface = false;
mFrameNumber = -1;
} else {
mCurrentFrameInfo->set(FrameInfoIndex::DequeueBufferDuration) = 0;
mCurrentFrameInfo->set(FrameInfoIndex::QueueBufferDuration) = 0;
+ mLast4FrameInfos[-1].second = -1;
}
// TODO: Use a fence for real completion?
@@ -537,6 +541,19 @@
mFrameMetricsReporter->reportFrameMetrics(mCurrentFrameInfo->data());
}
+ if (mLast4FrameInfos.size() == mLast4FrameInfos.capacity()) {
+ // By looking 4 frames back, we guarantee all SF stats are available. There are at
+ // most 3 buffers in BufferQueue. Surface object keeps stats for the last 8 frames.
+ FrameInfo* forthBehind = mLast4FrameInfos.front().first;
+ int64_t composedFrameId = mLast4FrameInfos.front().second;
+ nsecs_t acquireTime = -1;
+ mNativeSurface->getFrameTimestamps(composedFrameId, nullptr, &acquireTime, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr);
+ // Ignore default -1, NATIVE_WINDOW_TIMESTAMP_INVALID and NATIVE_WINDOW_TIMESTAMP_PENDING
+ forthBehind->set(FrameInfoIndex::GpuCompleted) = acquireTime > 0 ? acquireTime : -1;
+ mJankTracker.finishGpuDraw(*forthBehind);
+ }
+
GpuMemoryTracker::onFrameCompleted();
}
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index f9b9310..8a76d6b 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -29,6 +29,7 @@
#include "RenderNode.h"
#include "renderthread/RenderTask.h"
#include "renderthread/RenderThread.h"
+#include "utils/RingBuffer.h"
#include <SkBitmap.h>
#include <SkRect.h>
@@ -41,6 +42,7 @@
#include <future>
#include <set>
#include <string>
+#include <utility>
#include <vector>
namespace android {
@@ -260,6 +262,7 @@
std::vector<sp<RenderNode>> mRenderNodes;
FrameInfo* mCurrentFrameInfo = nullptr;
+ RingBuffer<std::pair<FrameInfo*, int64_t>, 4> mLast4FrameInfos;
std::string mName;
JankTracker mJankTracker;
FrameInfoVisualizer mProfiler;
diff --git a/libs/hwui/renderthread/ReliableSurface.h b/libs/hwui/renderthread/ReliableSurface.h
index 41fc35e..7f1a078 100644
--- a/libs/hwui/renderthread/ReliableSurface.h
+++ b/libs/hwui/renderthread/ReliableSurface.h
@@ -49,6 +49,21 @@
return ret;
}
+ status_t getFrameTimestamps(uint64_t frameNumber,
+ nsecs_t* outRequestedPresentTime, nsecs_t* outAcquireTime,
+ nsecs_t* outLatchTime, nsecs_t* outFirstRefreshStartTime,
+ nsecs_t* outLastRefreshStartTime, nsecs_t* outGlCompositionDoneTime,
+ nsecs_t* outDisplayPresentTime, nsecs_t* outDequeueReadyTime,
+ nsecs_t* outReleaseTime) {
+ return mSurface->getFrameTimestamps(frameNumber, outRequestedPresentTime, outAcquireTime,
+ outLatchTime, outFirstRefreshStartTime, outLastRefreshStartTime,
+ outGlCompositionDoneTime, outDisplayPresentTime, outDequeueReadyTime, outReleaseTime);
+ }
+
+ void enableFrameTimestamps(bool enable) {
+ return mSurface->enableFrameTimestamps(enable);
+ }
+
private:
const sp<Surface> mSurface;
diff --git a/libs/hwui/renderthread/RenderThread.h b/libs/hwui/renderthread/RenderThread.h
index df7eeb3..5aa1af3 100644
--- a/libs/hwui/renderthread/RenderThread.h
+++ b/libs/hwui/renderthread/RenderThread.h
@@ -53,6 +53,10 @@
class VkFunctorDrawHandler;
}
+namespace VectorDrawable {
+class Tree;
+}
+
namespace renderthread {
class CanvasContext;
@@ -138,6 +142,7 @@
friend class android::uirenderer::TestUtils;
friend class android::uirenderer::WebViewFunctor;
friend class android::uirenderer::skiapipeline::VkFunctorDrawHandler;
+ friend class android::uirenderer::VectorDrawable::Tree;
RenderThread();
virtual ~RenderThread();
diff --git a/libs/hwui/renderthread/VulkanSurface.h b/libs/hwui/renderthread/VulkanSurface.h
index 5717bb3..bd23626 100644
--- a/libs/hwui/renderthread/VulkanSurface.h
+++ b/libs/hwui/renderthread/VulkanSurface.h
@@ -18,6 +18,7 @@
#include <system/graphics.h>
#include <system/window.h>
#include <ui/BufferQueueDefs.h>
+#include <ui/PixelFormat.h>
#include <vulkan/vulkan.h>
#include <SkRefCnt.h>
diff --git a/libs/hwui/service/GraphicsStatsService.cpp b/libs/hwui/service/GraphicsStatsService.cpp
index 8a16b20..8b5912b 100644
--- a/libs/hwui/service/GraphicsStatsService.cpp
+++ b/libs/hwui/service/GraphicsStatsService.cpp
@@ -40,6 +40,7 @@
static_assert(sizeof(sCurrentFileVersion) == sHeaderSize, "Header size is wrong");
constexpr int sHistogramSize = ProfileData::HistogramSize();
+constexpr int sGPUHistogramSize = ProfileData::GPUHistogramSize();
static bool mergeProfileDataIntoProto(protos::GraphicsStatsProto* proto,
const std::string& package, int64_t versionCode,
@@ -211,6 +212,37 @@
bucket->set_frame_count(bucket->frame_count() + entry.frameCount);
index++;
});
+ if (hitMergeError) return false;
+ // fill in GPU frame time histogram
+ creatingHistogram = false;
+ if (proto->gpu_histogram_size() == 0) {
+ proto->mutable_gpu_histogram()->Reserve(sGPUHistogramSize);
+ creatingHistogram = true;
+ } else if (proto->gpu_histogram_size() != sGPUHistogramSize) {
+ ALOGE("GPU histogram size mismatch, proto is %d expected %d", proto->gpu_histogram_size(),
+ sGPUHistogramSize);
+ return false;
+ }
+ index = 0;
+ data->histogramGPUForEach([&](ProfileData::HistogramEntry entry) {
+ if (hitMergeError) return;
+
+ protos::GraphicsStatsHistogramBucketProto* bucket;
+ if (creatingHistogram) {
+ bucket = proto->add_gpu_histogram();
+ bucket->set_render_millis(entry.renderTimeMs);
+ } else {
+ bucket = proto->mutable_gpu_histogram(index);
+ if (bucket->render_millis() != static_cast<int32_t>(entry.renderTimeMs)) {
+ ALOGW("GPU frame time mistmatch %d vs. %u", bucket->render_millis(),
+ entry.renderTimeMs);
+ hitMergeError = true;
+ return;
+ }
+ }
+ bucket->set_frame_count(bucket->frame_count() + entry.frameCount);
+ index++;
+ });
return !hitMergeError;
}
@@ -226,6 +258,22 @@
return 0;
}
+static int32_t findGPUPercentile(protos::GraphicsStatsProto* proto, int percentile) {
+ uint32_t totalGPUFrameCount = 0; // this is usually proto->summary().total_frames() - 3.
+ for (auto it = proto->gpu_histogram().rbegin(); it != proto->gpu_histogram().rend(); ++it) {
+ totalGPUFrameCount += it->frame_count();
+ }
+ int32_t pos = percentile * totalGPUFrameCount / 100;
+ int32_t remaining = totalGPUFrameCount - pos;
+ for (auto it = proto->gpu_histogram().rbegin(); it != proto->gpu_histogram().rend(); ++it) {
+ remaining -= it->frame_count();
+ if (remaining <= 0) {
+ return it->render_millis();
+ }
+ }
+ return 0;
+}
+
void dumpAsTextToFd(protos::GraphicsStatsProto* proto, int fd) {
// This isn't a full validation, just enough that we can deref at will
if (proto->package_name().empty() || !proto->has_summary()) {
@@ -255,6 +303,14 @@
for (const auto& it : proto->histogram()) {
dprintf(fd, " %dms=%d", it.render_millis(), it.frame_count());
}
+ dprintf(fd, "\n50th gpu percentile: %dms", findGPUPercentile(proto, 50));
+ dprintf(fd, "\n90th gpu percentile: %dms", findGPUPercentile(proto, 90));
+ dprintf(fd, "\n95th gpu percentile: %dms", findGPUPercentile(proto, 95));
+ dprintf(fd, "\n99th gpu percentile: %dms", findGPUPercentile(proto, 99));
+ dprintf(fd, "\nGPU HISTOGRAM:");
+ for (const auto& it : proto->gpu_histogram()) {
+ dprintf(fd, " %dms=%d", it.render_millis(), it.frame_count());
+ }
dprintf(fd, "\n");
}
diff --git a/libs/hwui/tests/common/scenes/HwBitmapInCompositeShader.cpp b/libs/hwui/tests/common/scenes/HwBitmapInCompositeShader.cpp
index 3d0a2b2..5886ea3 100644
--- a/libs/hwui/tests/common/scenes/HwBitmapInCompositeShader.cpp
+++ b/libs/hwui/tests/common/scenes/HwBitmapInCompositeShader.cpp
@@ -50,7 +50,7 @@
pixels[4000 + 4 * i + 3] = 255;
}
buffer->unlock();
- sk_sp<Bitmap> hardwareBitmap(Bitmap::createFrom(buffer, kRGBA_8888_SkColorType,
+ sk_sp<Bitmap> hardwareBitmap(Bitmap::createFrom(buffer->toAHardwareBuffer(),
SkColorSpace::MakeSRGB()));
sk_sp<SkShader> hardwareShader(createBitmapShader(*hardwareBitmap));
diff --git a/libs/hwui/utils/Color.cpp b/libs/hwui/utils/Color.cpp
index cc7725b..9a27f28 100644
--- a/libs/hwui/utils/Color.cpp
+++ b/libs/hwui/utils/Color.cpp
@@ -19,12 +19,50 @@
#include <utils/Log.h>
#include <ui/ColorSpace.h>
+#ifdef __ANDROID__ // Layoutlib does not support hardware buffers or native windows
+#include <android/hardware_buffer.h>
+#endif
+
#include <algorithm>
#include <cmath>
namespace android {
namespace uirenderer {
+#ifdef __ANDROID__ // Layoutlib does not support hardware buffers or native windows
+SkImageInfo BufferDescriptionToImageInfo(const AHardwareBuffer_Desc& bufferDesc,
+ sk_sp<SkColorSpace> colorSpace) {
+ SkColorType colorType = kUnknown_SkColorType;
+ SkAlphaType alphaType = kOpaque_SkAlphaType;
+ switch (bufferDesc.format) {
+ case AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM:
+ colorType = kN32_SkColorType;
+ alphaType = kPremul_SkAlphaType;
+ break;
+ case AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM:
+ colorType = kN32_SkColorType;
+ alphaType = kOpaque_SkAlphaType;
+ break;
+ case AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM:
+ colorType = kRGB_565_SkColorType;
+ alphaType = kOpaque_SkAlphaType;
+ break;
+ case AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM:
+ colorType = kRGBA_1010102_SkColorType;
+ alphaType = kPremul_SkAlphaType;
+ break;
+ case AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT:
+ colorType = kRGBA_F16_SkColorType;
+ alphaType = kPremul_SkAlphaType;
+ break;
+ default:
+ ALOGV("Unsupported format: %d, return unknown by default", bufferDesc.format);
+ break;
+ }
+ return SkImageInfo::Make(bufferDesc.width, bufferDesc.height, colorType, alphaType, colorSpace);
+}
+#endif
+
android::PixelFormat ColorTypeToPixelFormat(SkColorType colorType) {
switch (colorType) {
case kRGBA_8888_SkColorType:
diff --git a/libs/hwui/utils/Color.h b/libs/hwui/utils/Color.h
index 79400de..7c2378a 100644
--- a/libs/hwui/utils/Color.h
+++ b/libs/hwui/utils/Color.h
@@ -25,6 +25,8 @@
#include <SkColorSpace.h>
#include <SkImageInfo.h>
+struct AHardwareBuffer_Desc;
+
namespace android {
namespace uirenderer {
namespace Color {
@@ -89,6 +91,9 @@
return srgb <= 0.04045f ? srgb / 12.92f : powf((srgb + 0.055f) / 1.055f, 2.4f);
}
+SkImageInfo BufferDescriptionToImageInfo(const AHardwareBuffer_Desc& bufferDesc,
+ sk_sp<SkColorSpace> colorSpace);
+
android::PixelFormat ColorTypeToPixelFormat(SkColorType colorType);
ANDROID_API SkColorType PixelFormatToColorType(android::PixelFormat format);
diff --git a/location/lib/Android.bp b/location/lib/Android.bp
index 16f1428..ab01ddb 100644
--- a/location/lib/Android.bp
+++ b/location/lib/Android.bp
@@ -21,7 +21,7 @@
"androidx.annotation_annotation",
],
api_packages: ["com.android.location.provider"],
- srcs_lib: "framework",
+ srcs_lib: "framework-minus-apex",
srcs_lib_whitelist_dirs: ["location/java"],
srcs_lib_whitelist_pkgs: ["com.android.internal.location"],
}
diff --git a/media/OWNERS b/media/OWNERS
index a33a990..8bd037a 100644
--- a/media/OWNERS
+++ b/media/OWNERS
@@ -10,6 +10,7 @@
jaewan@google.com
jmtrivi@google.com
jsharkey@android.com
+klhyun@google.com
lajos@google.com
marcone@google.com
sungsoo@google.com
diff --git a/media/java/android/media/AudioPortEventHandler.java b/media/java/android/media/AudioPortEventHandler.java
index f9a4b1e..6d9d626 100644
--- a/media/java/android/media/AudioPortEventHandler.java
+++ b/media/java/android/media/AudioPortEventHandler.java
@@ -19,10 +19,12 @@
import android.annotation.UnsupportedAppUsage;
import android.os.Handler;
import android.os.HandlerThread;
-import android.os.Looper;
import android.os.Message;
-import java.util.ArrayList;
+
+import com.android.internal.annotations.GuardedBy;
+
import java.lang.ref.WeakReference;
+import java.util.ArrayList;
/**
* The AudioPortEventHandler handles AudioManager.OnAudioPortUpdateListener callbacks
@@ -33,6 +35,9 @@
class AudioPortEventHandler {
private Handler mHandler;
private HandlerThread mHandlerThread;
+ private final Object mLock = new Object();
+
+ @GuardedBy("mLock")
private final ArrayList<AudioManager.OnAudioPortUpdateListener> mListeners =
new ArrayList<AudioManager.OnAudioPortUpdateListener>();
@@ -53,7 +58,7 @@
private long mJniCallback;
void init() {
- synchronized (this) {
+ synchronized (mLock) {
if (mHandler != null) {
return;
}
@@ -66,7 +71,7 @@
@Override
public void handleMessage(Message msg) {
ArrayList<AudioManager.OnAudioPortUpdateListener> listeners;
- synchronized (this) {
+ synchronized (mLock) {
if (msg.what == AUDIOPORT_EVENT_NEW_LISTENER) {
listeners = new ArrayList<AudioManager.OnAudioPortUpdateListener>();
if (mListeners.contains(msg.obj)) {
@@ -152,7 +157,7 @@
private native void native_finalize();
void registerListener(AudioManager.OnAudioPortUpdateListener l) {
- synchronized (this) {
+ synchronized (mLock) {
mListeners.add(l);
}
if (mHandler != null) {
@@ -162,7 +167,7 @@
}
void unregisterListener(AudioManager.OnAudioPortUpdateListener l) {
- synchronized (this) {
+ synchronized (mLock) {
mListeners.remove(l);
}
}
diff --git a/media/java/android/media/ExifInterface.java b/media/java/android/media/ExifInterface.java
index 7ae6a02..148ffaf 100644
--- a/media/java/android/media/ExifInterface.java
+++ b/media/java/android/media/ExifInterface.java
@@ -527,7 +527,7 @@
// Names for the data formats for debugging purpose.
private static final String[] IFD_FORMAT_NAMES = new String[] {
"", "BYTE", "STRING", "USHORT", "ULONG", "URATIONAL", "SBYTE", "UNDEFINED", "SSHORT",
- "SLONG", "SRATIONAL", "SINGLE", "DOUBLE"
+ "SLONG", "SRATIONAL", "SINGLE", "DOUBLE", "IFD"
};
// Sizes of the components of each IFD value format
private static final int[] IFD_FORMAT_BYTES_PER_FORMAT = new int[] {
diff --git a/media/java/android/media/MediaRouter2.java b/media/java/android/media/MediaRouter2.java
index a69b105..f4dffa2 100644
--- a/media/java/android/media/MediaRouter2.java
+++ b/media/java/android/media/MediaRouter2.java
@@ -16,12 +16,10 @@
package android.media;
-import android.annotation.MainThread;
+import android.annotation.CallbackExecutor;
import android.annotation.NonNull;
-import android.annotation.Nullable;
import android.content.Context;
import android.content.Intent;
-import android.os.Looper;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
@@ -30,9 +28,11 @@
import com.android.internal.annotations.GuardedBy;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
+import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.Executor;
@@ -43,7 +43,6 @@
public class MediaRouter2 {
private static final String TAG = "MediaRouter";
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
-
private static final Object sLock = new Object();
@GuardedBy("sLock")
@@ -51,134 +50,160 @@
private Context mContext;
private final IMediaRouterService mMediaRouterService;
- private List<CallbackRecord> mCallbackRecords = new ArrayList<>();
- final String mPackageName;
- IMediaRouter2Client mClient;
+ private CopyOnWriteArrayList<CallbackRecord> mCallbackRecords = new CopyOnWriteArrayList<>();
+ @GuardedBy("sLock")
+ private List<String> mControlCategories = Collections.emptyList();
+ @GuardedBy("sLock")
+ private Client mClient;
+
+ private final String mPackageName;
/**
* Gets an instance of the media router associated with the context.
*/
public static MediaRouter2 getInstance(@NonNull Context context) {
+ Objects.requireNonNull(context, "context must not be null");
synchronized (sLock) {
if (sInstance == null) {
- sInstance = new MediaRouter2(context);
+ sInstance = new MediaRouter2(context.getApplicationContext());
}
return sInstance;
}
}
- private MediaRouter2(Context context) {
- mContext = Objects.requireNonNull(context, "context must not be null");
+ private MediaRouter2(Context appContext) {
+ mContext = appContext;
mMediaRouterService = IMediaRouterService.Stub.asInterface(
ServiceManager.getService(Context.MEDIA_ROUTER_SERVICE));
mPackageName = mContext.getPackageName();
+ //TODO: read control categories from the manifest
}
/**
- * Registers a callback to discover routes that match the selector and to receive events
- * when they change.
+ * Registers a callback to discover routes and to receive events when they change.
*/
- @MainThread
- public void addCallback(@NonNull List<String> controlCategories, @NonNull Executor executor,
+ public void registerCallback(@NonNull @CallbackExecutor Executor executor,
@NonNull Callback callback) {
- addCallback(controlCategories, executor, callback, 0);
+ registerCallback(executor, callback, 0);
}
/**
- * Registers a callback to discover routes that match the selector and to receive events
- * when they change.
+ * Registers a callback to discover routes and to receive events when they change.
* <p>
- * If you add the same callback twice or more, the previous arguments will be overwritten
+ * If you register the same callback twice or more, the previous arguments will be overwritten
* with the new arguments.
* </p>
*/
- @MainThread
- public void addCallback(@NonNull List<String> controlCategories, @NonNull Executor executor,
+ public void registerCallback(@NonNull @CallbackExecutor Executor executor,
@NonNull Callback callback, int flags) {
- checkMainThread();
-
- Objects.requireNonNull(controlCategories, "control categories must not be null");
Objects.requireNonNull(executor, "executor must not be null");
Objects.requireNonNull(callback, "callback must not be null");
- if (mCallbackRecords.size() == 0) {
- Client client = new Client();
- try {
- mMediaRouterService.registerClient2AsUser(client, mPackageName,
- UserHandle.myUserId());
- //TODO: We should merge control categories of callbacks.
- mMediaRouterService.setControlCategories(client, controlCategories);
- mClient = client;
- } catch (RemoteException ex) {
- Log.e(TAG, "Unable to register media router.", ex);
+ // This is required to prevent adding the same callback twice.
+ synchronized (mCallbackRecords) {
+ if (mCallbackRecords.size() == 0) {
+ synchronized (sLock) {
+ Client client = new Client();
+ try {
+ mMediaRouterService.registerClient2AsUser(client, mPackageName,
+ UserHandle.myUserId());
+ //TODO: We should merge control categories of callbacks.
+ mMediaRouterService.setControlCategories(client, mControlCategories);
+ mClient = client;
+ } catch (RemoteException ex) {
+ Log.e(TAG, "Unable to register media router.", ex);
+ }
+ }
}
+
+ final int index = findCallbackRecordIndexLocked(callback);
+ CallbackRecord record;
+ if (index < 0) {
+ record = new CallbackRecord(callback);
+ mCallbackRecords.add(record);
+ } else {
+ record = mCallbackRecords.get(index);
+ }
+ record.mExecutor = executor;
+ record.mFlags = flags;
}
- final int index = findCallbackRecordIndex(callback);
- CallbackRecord record;
- if (index < 0) {
- record = new CallbackRecord(callback);
- mCallbackRecords.add(record);
- } else {
- record = mCallbackRecords.get(index);
- }
- record.mExecutor = executor;
- record.mControlCategories = controlCategories;
- record.mFlags = flags;
-
- //TODO: Check if we need an update.
+ //TODO: Update discovery request here.
}
/**
- * Removes the given callback. The callback will no longer receive events.
+ * Unregisters the given callback. The callback will no longer receive events.
* If the callback has not been added or been removed already, it is ignored.
- * @param callback the callback to remove.
- * @see #addCallback
+ *
+ * @param callback the callback to unregister
+ * @see #registerCallback
*/
- @MainThread
- public void removeCallback(@NonNull Callback callback) {
- checkMainThread();
-
+ public void unregisterCallback(@NonNull Callback callback) {
Objects.requireNonNull(callback, "callback must not be null");
- final int index = findCallbackRecordIndex(callback);
- if (index < 0) {
- Log.w(TAG, "Ignoring to remove unknown callback. " + callback);
- return;
- }
- mCallbackRecords.remove(index);
- if (mCallbackRecords.size() == 0 && mClient != null) {
- try {
- mMediaRouterService.unregisterClient2(mClient);
- } catch (RemoteException ex) {
- Log.e(TAG, "Unable to unregister media router.", ex);
+ synchronized (mCallbackRecords) {
+ final int index = findCallbackRecordIndexLocked(callback);
+ if (index < 0) {
+ Log.w(TAG, "Ignoring to remove unknown callback. " + callback);
+ return;
}
- mClient = null;
+ mCallbackRecords.remove(index);
+ synchronized (sLock) {
+ if (mCallbackRecords.size() == 0 && mClient != null) {
+ try {
+ mMediaRouterService.unregisterClient2(mClient);
+ } catch (RemoteException ex) {
+ Log.e(TAG, "Unable to unregister media router.", ex);
+ }
+ mClient = null;
+ }
+ }
}
}
- private int findCallbackRecordIndex(Callback callback) {
- final int count = mCallbackRecords.size();
- for (int i = 0; i < count; i++) {
- CallbackRecord callbackRecord = mCallbackRecords.get(i);
- if (callbackRecord.mCallback == callback) {
- return i;
+ //TODO(b/139033746): Rename "Control Category" when it's finalized.
+ /**
+ * Sets the control categories of the application.
+ * Routes that support at least one of the given control categories only exists and are handled
+ * by the media router.
+ */
+ public void setControlCategories(@NonNull Collection<String> controlCategories) {
+ Objects.requireNonNull(controlCategories, "control categories must not be null");
+
+ Client client;
+ List<String> newControlCategories;
+ synchronized (sLock) {
+ mControlCategories = new ArrayList<>(controlCategories);
+ newControlCategories = mControlCategories;
+ client = mClient;
+ }
+ if (client != null) {
+ try {
+ mMediaRouterService.setControlCategories(client, newControlCategories);
+ } catch (RemoteException ex) {
+ Log.e(TAG, "Unable to set control categories.", ex);
}
}
- return -1;
}
+
/**
* Selects the specified route.
*
- * @param route The route to select.
+ * @param route the route to select
*/
//TODO: add a parameter for category (e.g. mirroring/casting)
- public void selectRoute(@Nullable MediaRoute2Info route) {
- if (mClient != null) {
+ public void selectRoute(@NonNull MediaRoute2Info route) {
+ Objects.requireNonNull(route, "route must not be null");
+
+ Client client;
+ synchronized (sLock) {
+ client = mClient;
+ }
+ if (client != null) {
try {
- mMediaRouterService.selectRoute2(mClient, route);
+ mMediaRouterService.selectRoute2(client, route);
} catch (RemoteException ex) {
Log.e(TAG, "Unable to select route.", ex);
}
@@ -187,6 +212,7 @@
/**
* Sends a media control request to be performed asynchronously by the route's destination.
+ *
* @param route the route that will receive the control request
* @param request the media control request
*/
@@ -196,20 +222,29 @@
Objects.requireNonNull(route, "route must not be null");
Objects.requireNonNull(request, "request must not be null");
- if (mClient != null) {
+ Client client;
+ synchronized (sLock) {
+ client = mClient;
+ }
+ if (client != null) {
try {
- mMediaRouterService.sendControlRequest(mClient, route, request);
+ mMediaRouterService.sendControlRequest(client, route, request);
} catch (RemoteException ex) {
Log.e(TAG, "Unable to send control request.", ex);
}
}
}
- void checkMainThread() {
- Looper looper = Looper.myLooper();
- if (looper == null || looper != Looper.getMainLooper()) {
- throw new IllegalStateException("the method must be called on the main thread");
+ @GuardedBy("mCallbackRecords")
+ private int findCallbackRecordIndexLocked(Callback callback) {
+ final int count = mCallbackRecords.size();
+ for (int i = 0; i < count; i++) {
+ CallbackRecord callbackRecord = mCallbackRecords.get(i);
+ if (callbackRecord.mCallback == callback) {
+ return i;
+ }
}
+ return -1;
}
/**
@@ -232,15 +267,13 @@
public void onRouteRemoved(MediaRoute2Info routeInfo) {}
}
- final class CallbackRecord {
+ static final class CallbackRecord {
public final Callback mCallback;
public Executor mExecutor;
- public List<String> mControlCategories;
public int mFlags;
CallbackRecord(@NonNull Callback callback) {
- mCallback = Objects.requireNonNull(callback, "callback must not be null");
- mControlCategories = Collections.emptyList();
+ mCallback = callback;
}
}
diff --git a/media/java/android/media/MediaRouter2Manager.java b/media/java/android/media/MediaRouter2Manager.java
index 85105e0..6c53f7d 100644
--- a/media/java/android/media/MediaRouter2Manager.java
+++ b/media/java/android/media/MediaRouter2Manager.java
@@ -56,11 +56,10 @@
final String mPackageName;
private Context mContext;
+ @GuardedBy("sLock")
private Client mClient;
private final IMediaRouterService mMediaRouterService;
final Handler mHandler;
-
- @GuardedBy("sLock")
final List<CallbackRecord> mCallbacks = new CopyOnWriteArrayList<>();
@SuppressWarnings("WeakerAccess") /* synthetic access */
@@ -73,6 +72,7 @@
/**
* Gets an instance of media router manager that controls media route of other applications.
+ *
* @return The media router manager instance for the context.
*/
public static MediaRouter2Manager getInstance(@NonNull Context context) {
@@ -96,28 +96,29 @@
/**
* Registers a callback to listen route info.
*
- * @param executor The executor that runs the callback.
- * @param callback The callback to add.
+ * @param executor the executor that runs the callback
+ * @param callback the callback to add
*/
- public void addCallback(@NonNull @CallbackExecutor Executor executor,
+ public void registerCallback(@NonNull @CallbackExecutor Executor executor,
@NonNull Callback callback) {
-
Objects.requireNonNull(executor, "executor must not be null");
Objects.requireNonNull(callback, "callback must not be null");
- synchronized (sLock) {
- if (findCallbackRecordIndex(callback) >= 0) {
+ synchronized (mCallbacks) {
+ if (findCallbackRecordIndexLocked(callback) >= 0) {
Log.w(TAG, "Ignoring to add the same callback twice.");
return;
}
- if (mCallbacks.size() == 0) {
- Client client = new Client();
- try {
- mMediaRouterService.registerManagerAsUser(client, mPackageName,
- UserHandle.myUserId());
- mClient = client;
- } catch (RemoteException ex) {
- Log.e(TAG, "Unable to register media router manager.", ex);
+ synchronized (sLock) {
+ if (mCallbacks.size() == 0) {
+ Client client = new Client();
+ try {
+ mMediaRouterService.registerManagerAsUser(client, mPackageName,
+ UserHandle.myUserId());
+ mClient = client;
+ } catch (RemoteException ex) {
+ Log.e(TAG, "Unable to register media router manager.", ex);
+ }
}
}
CallbackRecord record = new CallbackRecord(executor, callback);
@@ -127,34 +128,35 @@
}
/**
- * Removes the specified callback.
+ * Unregisters the specified callback.
*
- * @param callback The callback to remove.
+ * @param callback the callback to unregister
*/
- public void removeCallback(@NonNull Callback callback) {
- if (callback == null) {
- throw new IllegalArgumentException("callback must not be null");
- }
+ public void unregisterCallback(@NonNull Callback callback) {
+ Objects.requireNonNull(callback, "callback must not be null");
- synchronized (sLock) {
- final int index = findCallbackRecordIndex(callback);
+ synchronized (mCallbacks) {
+ final int index = findCallbackRecordIndexLocked(callback);
if (index < 0) {
Log.w(TAG, "Ignore removing unknown callback. " + callback);
return;
}
mCallbacks.remove(index);
- if (mCallbacks.size() == 0 && mClient != null) {
- try {
- mMediaRouterService.unregisterManager(mClient);
- } catch (RemoteException ex) {
- Log.e(TAG, "Unable to unregister media router manager", ex);
+ synchronized (sLock) {
+ if (mCallbacks.size() == 0 && mClient != null) {
+ try {
+ mMediaRouterService.unregisterManager(mClient);
+ } catch (RemoteException ex) {
+ Log.e(TAG, "Unable to unregister media router manager", ex);
+ }
+ mClient = null;
}
- mClient = null;
}
}
}
- private int findCallbackRecordIndex(Callback callback) {
+ @GuardedBy("mCallbacks")
+ private int findCallbackRecordIndexLocked(Callback callback) {
final int count = mCallbacks.size();
for (int i = 0; i < count; i++) {
if (mCallbacks.get(i).mCallback == callback) {
@@ -173,6 +175,8 @@
*/
@NonNull
public List<MediaRoute2Info> getAvailableRoutes(@NonNull String packageName) {
+ Objects.requireNonNull(packageName, "packageName must not be null");
+
List<String> controlCategories = mControlCategoryMap.get(packageName);
if (controlCategories == null) {
return Collections.emptyList();
@@ -193,9 +197,16 @@
* @param route the route to be selected
*/
public void selectRoute(@NonNull String packageName, @NonNull MediaRoute2Info route) {
- if (mClient != null) {
+ Objects.requireNonNull(packageName, "packageName must not be null");
+ Objects.requireNonNull(route, "route must not be null");
+
+ Client client;
+ synchronized (sLock) {
+ client = mClient;
+ }
+ if (client != null) {
try {
- mMediaRouterService.selectClientRoute2(mClient, packageName, route);
+ mMediaRouterService.selectClientRoute2(client, packageName, route);
} catch (RemoteException ex) {
Log.e(TAG, "Unable to select media route", ex);
}
@@ -208,9 +219,13 @@
* @param packageName the package name of the application that should stop routing
*/
public void unselectRoute(@NonNull String packageName) {
- if (mClient != null) {
+ Client client;
+ synchronized (sLock) {
+ client = mClient;
+ }
+ if (client != null) {
try {
- mMediaRouterService.selectClientRoute2(mClient, packageName, null);
+ mMediaRouterService.selectClientRoute2(client, packageName, null);
} catch (RemoteException ex) {
Log.e(TAG, "Unable to select media route", ex);
}
@@ -227,10 +242,6 @@
return -1;
}
- MediaRoute2ProviderInfo getProvider(int index) {
- return mProviders.get(index);
- }
-
void updateProvider(@NonNull MediaRoute2ProviderInfo provider) {
if (provider == null || !provider.isValid()) {
Log.w(TAG, "Ignoring invalid provider : " + provider);
@@ -241,7 +252,7 @@
final int index = findProviderIndex(provider);
if (index >= 0) {
- final MediaRoute2ProviderInfo prevProvider = getProvider(index);
+ final MediaRoute2ProviderInfo prevProvider = mProviders.get(index);
final Set<String> updatedRouteIds = new HashSet<>();
for (MediaRoute2Info routeInfo : routes) {
final MediaRoute2Info prevRoute = prevProvider.getRoute(routeInfo.getId());
@@ -374,11 +385,9 @@
}
void notifyRoutes() {
- for (MediaRoute2ProviderInfo provider : mProviders) {
- for (MediaRoute2Info routeInfo : provider.getRoutes()) {
- mExecutor.execute(
- () -> mCallback.onRouteAdded(routeInfo));
- }
+ for (MediaRoute2Info routeInfo : mRoutes) {
+ mExecutor.execute(
+ () -> mCallback.onRouteAdded(routeInfo));
}
}
}
diff --git a/media/java/android/media/session/MediaSessionManager.java b/media/java/android/media/session/MediaSessionManager.java
index 1f2283c..6fd3342 100644
--- a/media/java/android/media/session/MediaSessionManager.java
+++ b/media/java/android/media/session/MediaSessionManager.java
@@ -16,6 +16,7 @@
package android.media.session;
+import android.annotation.CallbackExecutor;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
@@ -31,6 +32,7 @@
import android.media.Session2Token;
import android.os.Bundle;
import android.os.Handler;
+import android.os.HandlerExecutor;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.ResultReceiver;
@@ -50,6 +52,7 @@
import java.util.List;
import java.util.Map;
import java.util.Objects;
+import java.util.concurrent.Executor;
/**
* Provides support for interacting with {@link MediaSession media sessions}
@@ -86,7 +89,7 @@
@GuardedBy("mLock")
private final CallbackStub mCbStub = new CallbackStub();
@GuardedBy("mLock")
- private final Map<Callback, Handler> mCallbacks = new HashMap<>();
+ private final Map<Callback, Executor> mCallbacks = new HashMap<>();
@GuardedBy("mLock")
private MediaSession.Token mCurMediaButtonSession;
@GuardedBy("mLock")
@@ -765,13 +768,16 @@
*/
// TODO: Remove this method once Bluetooth app stop calling it.
public void setCallback(@Nullable Callback callback, @Nullable Handler handler) {
+ if (handler == null) {
+ handler = new Handler();
+ }
synchronized (mLock) {
if (mLegacyCallback != null) {
unregisterCallback(mLegacyCallback);
}
mLegacyCallback = callback;
if (callback != null) {
- registerCallback(callback, handler);
+ registerCallback(new HandlerExecutor(handler), callback);
}
}
}
@@ -779,27 +785,29 @@
/**
* Register a {@link Callback}.
*
+ * @param executor The executor on which the callback should be invoked
* @param callback A {@link Callback}.
- * @param handler The handler on which the callback should be invoked, or {@code null}
- * if the callback should be invoked on the calling thread's looper.
* @hide
*/
@SystemApi
@RequiresPermission(value = android.Manifest.permission.MEDIA_CONTENT_CONTROL)
- public void registerCallback(@NonNull Callback callback, @Nullable Handler handler) {
+ public void registerCallback(@NonNull @CallbackExecutor Executor executor,
+ @NonNull Callback callback) {
+ if (executor == null) {
+ throw new NullPointerException("executor shouldn't be null");
+ }
if (callback == null) {
throw new NullPointerException("callback shouldn't be null");
}
synchronized (mLock) {
try {
- if (handler == null) {
- handler = new Handler();
- }
- mCallbacks.put(callback, handler);
+ mCallbacks.put(callback, executor);
if (mCurMediaButtonSession != null) {
- handler.post(() -> callback.onAddressedPlayerChanged(mCurMediaButtonSession));
+ executor.execute(
+ () -> callback.onAddressedPlayerChanged(mCurMediaButtonSession));
} else if (mCurMediaButtonReceiver != null) {
- handler.post(() -> callback.onAddressedPlayerChanged(mCurMediaButtonReceiver));
+ executor.execute(
+ () -> callback.onAddressedPlayerChanged(mCurMediaButtonReceiver));
}
if (mCallbacks.size() == 1) {
@@ -1147,8 +1155,8 @@
public void onMediaKeyEventDispatchedToMediaSession(KeyEvent event,
MediaSession.Token sessionToken) {
synchronized (mLock) {
- for (Map.Entry<Callback, Handler> e : mCallbacks.entrySet()) {
- e.getValue().post(
+ for (Map.Entry<Callback, Executor> e : mCallbacks.entrySet()) {
+ e.getValue().execute(
() -> e.getKey().onMediaKeyEventDispatched(event, sessionToken));
}
}
@@ -1158,8 +1166,8 @@
public void onMediaKeyEventDispatchedToMediaButtonReceiver(KeyEvent event,
ComponentName mediaButtonReceiver) {
synchronized (mLock) {
- for (Map.Entry<Callback, Handler> e : mCallbacks.entrySet()) {
- e.getValue().post(
+ for (Map.Entry<Callback, Executor> e : mCallbacks.entrySet()) {
+ e.getValue().execute(
() -> e.getKey().onMediaKeyEventDispatched(event, mediaButtonReceiver));
}
}
@@ -1170,8 +1178,8 @@
synchronized (mLock) {
mCurMediaButtonSession = sessionToken;
mCurMediaButtonReceiver = null;
- for (Map.Entry<Callback, Handler> e : mCallbacks.entrySet()) {
- e.getValue().post(() -> e.getKey().onAddressedPlayerChanged(sessionToken));
+ for (Map.Entry<Callback, Executor> e : mCallbacks.entrySet()) {
+ e.getValue().execute(() -> e.getKey().onAddressedPlayerChanged(sessionToken));
}
}
}
@@ -1182,8 +1190,8 @@
synchronized (mLock) {
mCurMediaButtonSession = null;
mCurMediaButtonReceiver = mediaButtonReceiver;
- for (Map.Entry<Callback, Handler> e : mCallbacks.entrySet()) {
- e.getValue().post(() -> e.getKey().onAddressedPlayerChanged(
+ for (Map.Entry<Callback, Executor> e : mCallbacks.entrySet()) {
+ e.getValue().execute(() -> e.getKey().onAddressedPlayerChanged(
mediaButtonReceiver));
}
}
diff --git a/media/jni/android_media_ImageWriter.cpp b/media/jni/android_media_ImageWriter.cpp
index e9d7f8b..4a9da62 100644
--- a/media/jni/android_media_ImageWriter.cpp
+++ b/media/jni/android_media_ImageWriter.cpp
@@ -26,6 +26,7 @@
#include <gui/IProducerListener.h>
#include <gui/Surface.h>
+#include <ui/PublicFormat.h>
#include <android_runtime/AndroidRuntime.h>
#include <android_runtime/android_view_Surface.h>
#include <android_runtime/android_hardware_HardwareBuffer.h>
@@ -401,8 +402,28 @@
return 0;
}
} else {
+ // Set consumer buffer format to user specified format
+ PublicFormat publicFormat = static_cast<PublicFormat>(userFormat);
+ int nativeFormat = mapPublicFormatToHalFormat(publicFormat);
+ android_dataspace nativeDataspace = mapPublicFormatToHalDataspace(publicFormat);
+ res = native_window_set_buffers_format(anw.get(), nativeFormat);
+ if (res != OK) {
+ ALOGE("%s: Unable to configure consumer native buffer format to %#x",
+ __FUNCTION__, nativeFormat);
+ jniThrowRuntimeException(env, "Failed to set Surface format");
+ return 0;
+ }
+
+ res = native_window_set_buffers_data_space(anw.get(), nativeDataspace);
+ if (res != OK) {
+ ALOGE("%s: Unable to configure consumer dataspace %#x",
+ __FUNCTION__, nativeDataspace);
+ jniThrowRuntimeException(env, "Failed to set Surface dataspace");
+ return 0;
+ }
surfaceFormat = userFormat;
}
+
ctx->setBufferFormat(surfaceFormat);
env->SetIntField(thiz,
gImageWriterClassInfo.mWriterFormat, reinterpret_cast<jint>(surfaceFormat));
diff --git a/media/lib/signer/Android.bp b/media/lib/signer/Android.bp
index 44f8725..f320397 100644
--- a/media/lib/signer/Android.bp
+++ b/media/lib/signer/Android.bp
@@ -18,7 +18,7 @@
name: "com.android.mediadrm.signer",
srcs: ["java/**/*.java"],
api_packages: ["com.android.mediadrm.signer"],
- srcs_lib: "framework",
+ srcs_lib: "framework-minus-apex",
srcs_lib_whitelist_dirs: ["media/java"],
srcs_lib_whitelist_pkgs: ["android.media"],
}
diff --git a/media/native/midi/amidi.cpp b/media/native/midi/amidi.cpp
index 357bb5e5..46f2815 100644
--- a/media/native/midi/amidi.cpp
+++ b/media/native/midi/amidi.cpp
@@ -142,7 +142,7 @@
return AMEDIA_OK;
}
-media_status_t AMidiDevice_fromJava(JNIEnv *env, jobject j_midiDeviceObj,
+media_status_t AMIDI_API AMidiDevice_fromJava(JNIEnv *env, jobject j_midiDeviceObj,
AMidiDevice** devicePtrPtr)
{
if (j_midiDeviceObj == nullptr) {
@@ -188,7 +188,7 @@
return AMEDIA_OK;
}
-media_status_t AMidiDevice_release(const AMidiDevice *device)
+media_status_t AMIDI_API AMidiDevice_release(const AMidiDevice *device)
{
if (device == nullptr || device->midiDeviceObj == nullptr) {
return AMEDIA_ERROR_INVALID_PARAMETER;
@@ -217,21 +217,21 @@
return AMEDIA_OK;
}
-int32_t AMidiDevice_getType(const AMidiDevice *device) {
+int32_t AMIDI_API AMidiDevice_getType(const AMidiDevice *device) {
if (device == nullptr) {
return AMEDIA_ERROR_INVALID_PARAMETER;
}
return device->deviceInfo.type;
}
-ssize_t AMidiDevice_getNumInputPorts(const AMidiDevice *device) {
+ssize_t AMIDI_API AMidiDevice_getNumInputPorts(const AMidiDevice *device) {
if (device == nullptr) {
return AMEDIA_ERROR_INVALID_PARAMETER;
}
return device->deviceInfo.inputPortCount;
}
-ssize_t AMidiDevice_getNumOutputPorts(const AMidiDevice *device) {
+ssize_t AMIDI_API AMidiDevice_getNumOutputPorts(const AMidiDevice *device) {
if (device == nullptr) {
return AMEDIA_ERROR_INVALID_PARAMETER;
}
@@ -291,7 +291,7 @@
/*
* Output (receiving) API
*/
-media_status_t AMidiOutputPort_open(const AMidiDevice *device, int32_t portNumber,
+media_status_t AMIDI_API AMidiOutputPort_open(const AMidiDevice *device, int32_t portNumber,
AMidiOutputPort **outOutputPortPtr) {
return AMIDI_openPort(device, portNumber, PORTTYPE_OUTPUT, (AMIDI_Port**)outOutputPortPtr);
}
@@ -350,7 +350,7 @@
AMIDI_Port *mPort;
};
-ssize_t AMidiOutputPort_receive(const AMidiOutputPort *outputPort, int32_t *opcodePtr,
+ssize_t AMIDI_API AMidiOutputPort_receive(const AMidiOutputPort *outputPort, int32_t *opcodePtr,
uint8_t *buffer, size_t maxBytes, size_t* numBytesReceivedPtr, int64_t *timestampPtr) {
if (outputPort == nullptr || buffer == nullptr) {
@@ -361,19 +361,19 @@
numBytesReceivedPtr, timestampPtr);
}
-void AMidiOutputPort_close(const AMidiOutputPort *outputPort) {
+void AMIDI_API AMidiOutputPort_close(const AMidiOutputPort *outputPort) {
AMIDI_closePort((AMIDI_Port*)outputPort);
}
/*
* Input (sending) API
*/
-media_status_t AMidiInputPort_open(const AMidiDevice *device, int32_t portNumber,
+media_status_t AMIDI_API AMidiInputPort_open(const AMidiDevice *device, int32_t portNumber,
AMidiInputPort **outInputPortPtr) {
return AMIDI_openPort(device, portNumber, PORTTYPE_INPUT, (AMIDI_Port**)outInputPortPtr);
}
-void AMidiInputPort_close(const AMidiInputPort *inputPort) {
+void AMIDI_API AMidiInputPort_close(const AMidiInputPort *inputPort) {
AMIDI_closePort((AMIDI_Port*)inputPort);
}
@@ -386,12 +386,12 @@
return numBytes + AMIDI_PACKET_OVERHEAD;
}
-ssize_t AMidiInputPort_send(const AMidiInputPort *inputPort, const uint8_t *buffer,
+ssize_t AMIDI_API AMidiInputPort_send(const AMidiInputPort *inputPort, const uint8_t *buffer,
size_t numBytes) {
return AMidiInputPort_sendWithTimestamp(inputPort, buffer, numBytes, 0);
}
-ssize_t AMidiInputPort_sendWithTimestamp(const AMidiInputPort *inputPort,
+ssize_t AMIDI_API AMidiInputPort_sendWithTimestamp(const AMidiInputPort *inputPort,
const uint8_t *data, size_t numBytes, int64_t timestamp) {
if (inputPort == nullptr || data == nullptr) {
return AMEDIA_ERROR_INVALID_PARAMETER;
@@ -423,7 +423,7 @@
return numSent;
}
-media_status_t AMidiInputPort_sendFlush(const AMidiInputPort *inputPort) {
+media_status_t AMIDI_API AMidiInputPort_sendFlush(const AMidiInputPort *inputPort) {
if (inputPort == nullptr) {
return AMEDIA_ERROR_INVALID_PARAMETER;
}
diff --git a/media/native/midi/include/amidi/AMidi.h b/media/native/midi/include/amidi/AMidi.h
index 76dec0f..0f930b5 100644
--- a/media/native/midi/include/amidi/AMidi.h
+++ b/media/native/midi/include/amidi/AMidi.h
@@ -37,6 +37,8 @@
extern "C" {
#endif
+#define AMIDI_API __attribute__((visibility("default")))
+
typedef struct AMidiDevice AMidiDevice;
typedef struct AMidiInputPort AMidiInputPort;
typedef struct AMidiOutputPort AMidiOutputPort;
@@ -78,7 +80,7 @@
* is null or already connected to a native AMidiDevice
* @see AMEDIA_ERROR_UNKNOWN - an unknown error occurred.
*/
-media_status_t AMidiDevice_fromJava(
+media_status_t AMIDI_API AMidiDevice_fromJava(
JNIEnv *env, jobject midiDeviceObj, AMidiDevice **outDevicePtrPtr) __INTRODUCED_IN(29);
/**
@@ -93,7 +95,7 @@
* @see AMEDIA_ERROR_INVALID_OBJECT - the JNI interface initialization to the associated java MidiDevice failed.
* @see AMEDIA_ERROR_UNKNOWN - couldn't retrieve the device info.
*/
-media_status_t AMidiDevice_release(const AMidiDevice *midiDevice) __INTRODUCED_IN(29);
+media_status_t AMIDI_API AMidiDevice_release(const AMidiDevice *midiDevice) __INTRODUCED_IN(29);
/**
* Gets the MIDI device type.
@@ -108,7 +110,7 @@
* @see AMEDIA_ERROR_INVALID_PARAMETER - the device parameter is NULL.
* @see AMEDIA_ERROR_UNKNOWN - Unknown error.
*/
-int32_t AMidiDevice_getType(const AMidiDevice *device) __INTRODUCED_IN(29);
+int32_t AMIDI_API AMidiDevice_getType(const AMidiDevice *device) __INTRODUCED_IN(29);
/**
* Gets the number of input (sending) ports available on the specified MIDI device.
@@ -120,7 +122,7 @@
* @see AMEDIA_ERROR_INVALID_PARAMETER - the device parameter is NULL.
* @see AMEDIA_ERROR_UNKNOWN - couldn't retrieve the device info.
*/
-ssize_t AMidiDevice_getNumInputPorts(const AMidiDevice *device) __INTRODUCED_IN(29);
+ssize_t AMIDI_API AMidiDevice_getNumInputPorts(const AMidiDevice *device) __INTRODUCED_IN(29);
/**
* Gets the number of output (receiving) ports available on the specified MIDI device.
@@ -132,7 +134,7 @@
* @see AMEDIA_ERROR_INVALID_PARAMETER - the device parameter is NULL.
* @see AMEDIA_ERROR_UNKNOWN - couldn't retrieve the device info.
*/
-ssize_t AMidiDevice_getNumOutputPorts(const AMidiDevice *device) __INTRODUCED_IN(29);
+ssize_t AMIDI_API AMidiDevice_getNumOutputPorts(const AMidiDevice *device) __INTRODUCED_IN(29);
/*
* API for receiving data from the Output port of a device.
@@ -150,7 +152,7 @@
* @return AMEDIA_OK, or a negative error code:
* @see AMEDIA_ERROR_UNKNOWN - Unknown Error.
*/
-media_status_t AMidiOutputPort_open(const AMidiDevice *device, int32_t portNumber,
+media_status_t AMIDI_API AMidiOutputPort_open(const AMidiDevice *device, int32_t portNumber,
AMidiOutputPort **outOutputPortPtr) __INTRODUCED_IN(29);
/**
@@ -158,7 +160,7 @@
*
* @param outputPort The native API port identifier of the port.
*/
-void AMidiOutputPort_close(const AMidiOutputPort *outputPort) __INTRODUCED_IN(29);
+void AMIDI_API AMidiOutputPort_close(const AMidiOutputPort *outputPort) __INTRODUCED_IN(29);
/**
* Receives the next pending MIDI message. To retrieve all pending messages, the client should
@@ -178,7 +180,7 @@
* @return the number of messages received (either 0 or 1), or a negative error code:
* @see AMEDIA_ERROR_UNKNOWN - Unknown Error.
*/
-ssize_t AMidiOutputPort_receive(const AMidiOutputPort *outputPort, int32_t *opcodePtr,
+ssize_t AMIDI_API AMidiOutputPort_receive(const AMidiOutputPort *outputPort, int32_t *opcodePtr,
uint8_t *buffer, size_t maxBytes, size_t* numBytesReceivedPtr, int64_t *outTimestampPtr) __INTRODUCED_IN(29);
/*
@@ -197,7 +199,7 @@
* @return AMEDIA_OK, or a negative error code:
* @see AMEDIA_ERROR_UNKNOWN - Unknown Error.
*/
-media_status_t AMidiInputPort_open(const AMidiDevice *device, int32_t portNumber,
+media_status_t AMIDI_API AMidiInputPort_open(const AMidiDevice *device, int32_t portNumber,
AMidiInputPort **outInputPortPtr) __INTRODUCED_IN(29);
/**
@@ -210,7 +212,7 @@
* @return The number of bytes sent, which could be less than specified or a negative error code:
* @see AMEDIA_ERROR_INVALID_PARAMETER - The specified port was NULL, the specified buffer was NULL.
*/
-ssize_t AMidiInputPort_send(const AMidiInputPort *inputPort, const uint8_t *buffer,
+ssize_t AMIDI_API AMidiInputPort_send(const AMidiInputPort *inputPort, const uint8_t *buffer,
size_t numBytes) __INTRODUCED_IN(29);
/**
@@ -224,7 +226,7 @@
* @return The number of bytes sent, which could be less than specified or a negative error code:
* @see AMEDIA_ERROR_INVALID_PARAMETER - The specified port was NULL, the specified buffer was NULL.
*/
-ssize_t AMidiInputPort_sendWithTimestamp(const AMidiInputPort *inputPort,
+ssize_t AMIDI_API AMidiInputPort_sendWithTimestamp(const AMidiInputPort *inputPort,
const uint8_t *buffer, size_t numBytes, int64_t timestamp) __INTRODUCED_IN(29);
/**
@@ -238,14 +240,14 @@
* @see AMEDIA_ERROR_UNSUPPORTED - The FLUSH command couldn't
* be sent.
*/
-media_status_t AMidiInputPort_sendFlush(const AMidiInputPort *inputPort) __INTRODUCED_IN(29);
+media_status_t AMIDI_API AMidiInputPort_sendFlush(const AMidiInputPort *inputPort) __INTRODUCED_IN(29);
/**
* Closes the input port.
*
* @param inputPort Identifies the input (sending) port to close.
*/
-void AMidiInputPort_close(const AMidiInputPort *inputPort) __INTRODUCED_IN(29);
+void AMIDI_API AMidiInputPort_close(const AMidiInputPort *inputPort) __INTRODUCED_IN(29);
#endif /* __ANDROID_API__ >= 29 */
diff --git a/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouterManagerTest.java b/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouterManagerTest.java
index 4282a5bc..946fb5e 100644
--- a/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouterManagerTest.java
+++ b/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouterManagerTest.java
@@ -44,8 +44,7 @@
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
-import java.util.concurrent.SynchronousQueue;
-import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
@RunWith(AndroidJUnit4.class)
@@ -92,9 +91,8 @@
mContext = InstrumentationRegistry.getTargetContext();
mManager = MediaRouter2Manager.getInstance(mContext);
mRouter = MediaRouter2.getInstance(mContext);
- mExecutor = new ThreadPoolExecutor(
- 1, 20, 3, TimeUnit.SECONDS,
- new SynchronousQueue<Runnable>());
+ //TODO: If we need to support thread pool executors, change this to thread pool executor.
+ mExecutor = Executors.newSingleThreadExecutor();
mPackageName = mContext.getPackageName();
}
@@ -116,36 +114,34 @@
public void testRouteAdded() {
MediaRouter2Manager.Callback mockCallback = mock(MediaRouter2Manager.Callback.class);
- mManager.addCallback(mExecutor, mockCallback);
+ mManager.registerCallback(mExecutor, mockCallback);
verify(mockCallback, timeout(TIMEOUT_MS)).onRouteAdded(argThat(
(MediaRoute2Info info) ->
info.getId().equals(ROUTE_ID1) && info.getName().equals(ROUTE_NAME1)));
- mManager.removeCallback(mockCallback);
+ mManager.unregisterCallback(mockCallback);
}
//TODO: Recover this test when media router 2 is finalized.
public void testRouteRemoved() {
MediaRouter2Manager.Callback mockCallback = mock(MediaRouter2Manager.Callback.class);
- mManager.addCallback(mExecutor, mockCallback);
+ mManager.registerCallback(mExecutor, mockCallback);
MediaRouter2.Callback mockRouterCallback = mock(MediaRouter2.Callback.class);
//TODO: Figure out a more proper way to test.
// (Control requests shouldn't be used in this way.)
- InstrumentationRegistry.getInstrumentation().runOnMainSync(
- (Runnable) () -> {
- mRouter.addCallback(CONTROL_CATEGORIES_ALL, mExecutor, mockRouterCallback);
- mRouter.sendControlRequest(
- new MediaRoute2Info.Builder(ROUTE_ID2, ROUTE_NAME2).build(),
- new Intent(ACTION_REMOVE_ROUTE));
- mRouter.removeCallback(mockRouterCallback);
- }
- );
+ mRouter.setControlCategories(CONTROL_CATEGORIES_ALL);
+ mRouter.registerCallback(mExecutor, mockRouterCallback);
+ mRouter.sendControlRequest(
+ new MediaRoute2Info.Builder(ROUTE_ID2, ROUTE_NAME2).build(),
+ new Intent(ACTION_REMOVE_ROUTE));
+ mRouter.unregisterCallback(mockRouterCallback);
+
verify(mockCallback, timeout(TIMEOUT_MS)).onRouteRemoved(argThat(
(MediaRoute2Info info) ->
info.getId().equals(ROUTE_ID2) && info.getName().equals(ROUTE_NAME2)));
- mManager.removeCallback(mockCallback);
+ mManager.unregisterCallback(mockCallback);
}
/**
@@ -154,17 +150,14 @@
@Test
public void testControlCategory() throws Exception {
MediaRouter2Manager.Callback mockCallback = mock(MediaRouter2Manager.Callback.class);
- mManager.addCallback(mExecutor, mockCallback);
+ mManager.registerCallback(mExecutor, mockCallback);
MediaRouter2.Callback mockRouterCallback = mock(MediaRouter2.Callback.class);
- InstrumentationRegistry.getInstrumentation().runOnMainSync(
- () -> {
- mRouter.addCallback(CONTROL_CATEGORIES_SPECIAL,
- mExecutor, mockRouterCallback);
- mRouter.removeCallback(mockRouterCallback);
- }
- );
+ mRouter.setControlCategories(CONTROL_CATEGORIES_SPECIAL);
+ mRouter.registerCallback(mExecutor, mockRouterCallback);
+ mRouter.unregisterCallback(mockRouterCallback);
+
verify(mockCallback, timeout(TIMEOUT_MS))
.onRouteListChanged(argThat(routes -> routes.size() > 0));
@@ -174,7 +167,7 @@
Assert.assertEquals(1, routes.size());
Assert.assertNotNull(routes.get(ROUTE_ID_SPECIAL_CATEGORY));
- mManager.removeCallback(mockCallback);
+ mManager.unregisterCallback(mockCallback);
}
@Test
@@ -182,11 +175,7 @@
CountDownLatch latch = new CountDownLatch(1);
MediaRouter2.Callback mockRouterCallback = mock(MediaRouter2.Callback.class);
- InstrumentationRegistry.getInstrumentation().runOnMainSync(
- () -> {
- mRouter.addCallback(CONTROL_CATEGORIES_ALL, mExecutor, mockRouterCallback);
- }
- );
+ mRouter.registerCallback(mExecutor, mockRouterCallback);
MediaRouter2Manager.Callback managerCallback = new MediaRouter2Manager.Callback() {
MediaRoute2Info mSelectedRoute = null;
@@ -210,11 +199,11 @@
}
};
- mManager.addCallback(mExecutor, managerCallback);
+ mManager.registerCallback(mExecutor, managerCallback);
Assert.assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
- mManager.removeCallback(managerCallback);
+ mManager.unregisterCallback(managerCallback);
}
/**
@@ -225,12 +214,10 @@
MediaRouter2Manager.Callback managerCallback = mock(MediaRouter2Manager.Callback.class);
MediaRouter2.Callback routerCallback = mock(MediaRouter2.Callback.class);
- mManager.addCallback(mExecutor, managerCallback);
- InstrumentationRegistry.getInstrumentation().runOnMainSync(
- () -> {
- mRouter.addCallback(CONTROL_CATEGORIES_ALL, mExecutor, routerCallback);
- }
- );
+ mManager.registerCallback(mExecutor, managerCallback);
+ mRouter.setControlCategories(CONTROL_CATEGORIES_ALL);
+ mRouter.registerCallback(mExecutor, routerCallback);
+
verify(managerCallback, timeout(TIMEOUT_MS))
.onRouteListChanged(argThat(routes -> routes.size() > 0));
@@ -253,12 +240,8 @@
.onRouteChanged(argThat(routeInfo -> TextUtils.equals(ROUTE_ID2, routeInfo.getId())
&& TextUtils.equals(routeInfo.getClientPackageName(), null)));
- InstrumentationRegistry.getInstrumentation().runOnMainSync(
- () -> {
- mRouter.removeCallback(routerCallback);
- }
- );
- mManager.removeCallback(managerCallback);
+ mRouter.unregisterCallback(routerCallback);
+ mManager.unregisterCallback(managerCallback);
}
Map<String, MediaRoute2Info> createRouteMap(List<MediaRoute2Info> routes) {
diff --git a/packages/CompanionDeviceManager/OWNERS b/packages/CompanionDeviceManager/OWNERS
new file mode 100644
index 0000000..da723b3
--- /dev/null
+++ b/packages/CompanionDeviceManager/OWNERS
@@ -0,0 +1 @@
+eugenesusla@google.com
\ No newline at end of file
diff --git a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java
index d0ca04b..d11b5c5 100644
--- a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java
+++ b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java
@@ -24,6 +24,7 @@
import static com.android.internal.util.CollectionUtils.size;
import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage;
+import android.annotation.MainThread;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.PendingIntent;
@@ -115,7 +116,8 @@
}
mFindCallback = findCallback;
mServiceCallback = serviceCallback;
- DeviceDiscoveryService.this.startDiscovery(request);
+ Handler.getMain().sendMessage(obtainMessage(
+ DeviceDiscoveryService::startDiscovery, DeviceDiscoveryService.this, request));
}
};
@@ -145,6 +147,7 @@
sInstance = this;
}
+ @MainThread
private void startDiscovery(AssociationRequest request) {
if (!request.equals(mRequest)) {
mRequest = request;
@@ -211,12 +214,13 @@
return !isEmpty(mediumSpecificFilters) || isEmpty(mFilters);
}
+ @MainThread
private void reset() {
if (DEBUG) Log.i(LOG_TAG, "reset()");
stopScan();
mDevicesFound.clear();
mSelectedDevice = null;
- notifyDataSetChanged();
+ mDevicesAdapter.notifyDataSetChanged();
}
@Override
@@ -260,16 +264,17 @@
if (DEBUG) Log.i(LOG_TAG, "Found device " + device);
+ Handler.getMain().sendMessage(obtainMessage(
+ DeviceDiscoveryService::onDeviceFoundMainThread, this, device));
+ }
+
+ @MainThread
+ void onDeviceFoundMainThread(@NonNull DeviceFilterPair device) {
if (mDevicesFound.isEmpty()) {
onReadyToShowUI();
}
mDevicesFound.add(device);
- notifyDataSetChanged();
- }
-
- private void notifyDataSetChanged() {
- Handler.getMain().sendMessage(obtainMessage(
- DevicesAdapter::notifyDataSetChanged, mDevicesAdapter));
+ mDevicesAdapter.notifyDataSetChanged();
}
//TODO also, on timeout -> call onFailure
@@ -286,9 +291,15 @@
}
private void onDeviceLost(@Nullable DeviceFilterPair device) {
- mDevicesFound.remove(device);
- notifyDataSetChanged();
if (DEBUG) Log.i(LOG_TAG, "Lost device " + device.getDisplayName());
+ Handler.getMain().sendMessage(obtainMessage(
+ DeviceDiscoveryService::onDeviceLostMainThread, this, device));
+ }
+
+ @MainThread
+ void onDeviceLostMainThread(@Nullable DeviceFilterPair device) {
+ mDevicesFound.remove(device);
+ mDevicesAdapter.notifyDataSetChanged();
}
void onDeviceSelected(String callingPackage, String deviceAddress) {
diff --git a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java
index e731b45..142078e 100644
--- a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java
+++ b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java
@@ -291,7 +291,7 @@
if (mInstallTask != null && mInstallTask.getResult() == RESULT_OK) {
enabled = mInstallTask.commit();
} else if (isDynamicSystemInstalled()) {
- enabled = mDynSystem.setEnable(true);
+ enabled = mDynSystem.setEnable(true, true);
} else {
Log.e(TAG, "Trying to reboot to AOT while there is no complete installation");
return;
diff --git a/packages/MtpDocumentsProvider/Android.bp b/packages/MtpDocumentsProvider/Android.bp
deleted file mode 100644
index 3dafa26..0000000
--- a/packages/MtpDocumentsProvider/Android.bp
+++ /dev/null
@@ -1,11 +0,0 @@
-android_app {
- name: "MtpDocumentsProvider",
-
- srcs: ["src/**/*.java"],
- platform_apis: true,
- certificate: "media",
- privileged: true,
- optimize: {
- proguard_flags_files: ["proguard.flags"],
- },
-}
diff --git a/packages/MtpDocumentsProvider/AndroidManifest.xml b/packages/MtpDocumentsProvider/AndroidManifest.xml
deleted file mode 100644
index c0a59b3..0000000
--- a/packages/MtpDocumentsProvider/AndroidManifest.xml
+++ /dev/null
@@ -1,43 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.mtp"
- android:sharedUserId="android.media">
- <uses-feature android:name="android.hardware.usb.host" />
- <uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
- <uses-permission android:name="android.permission.MANAGE_USB" />
- <application android:label="@string/app_label">
- <provider
- android:name=".MtpDocumentsProvider"
- android:authorities="com.android.mtp.documents"
- android:grantUriPermissions="true"
- android:exported="true"
- android:permission="android.permission.MANAGE_DOCUMENTS">
- <intent-filter>
- <action android:name="android.content.action.DOCUMENTS_PROVIDER" />
- </intent-filter>
- </provider>
-
- <service android:name=".MtpDocumentsService" />
-
- <activity android:name=".ReceiverActivity"
- android:label="@string/downloads_app_label"
- android:icon="@mipmap/ic_launcher_download"
- android:theme="@android:style/Theme.NoDisplay"
- android:excludeFromRecents="true">
- <intent-filter>
- <action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
- </intent-filter>
- <meta-data android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"
- android:resource="@xml/device_filter" />
- </activity>
-
- <receiver android:name=".UsbIntentReceiver" android:exported="true">
- <intent-filter>
- <action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
- <action android:name="android.hardware.usb.action.USB_DEVICE_DETACHED" />
- </intent-filter>
- <meta-data android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"
- android:resource="@xml/device_filter" />
- </receiver>
- </application>
-</manifest>
diff --git a/packages/MtpDocumentsProvider/MOVED b/packages/MtpDocumentsProvider/MOVED
new file mode 100644
index 0000000..6c8a519
--- /dev/null
+++ b/packages/MtpDocumentsProvider/MOVED
@@ -0,0 +1 @@
+../../../../packages/services/Mtp
diff --git a/packages/MtpDocumentsProvider/perf_tests/Android.mk b/packages/MtpDocumentsProvider/perf_tests/Android.mk
deleted file mode 100644
index d2f1c7a..0000000
--- a/packages/MtpDocumentsProvider/perf_tests/Android.mk
+++ /dev/null
@@ -1,13 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_STATIC_JAVA_LIBRARIES := androidx.test.rules
-LOCAL_PACKAGE_NAME := MtpDocumentsProviderPerfTests
-LOCAL_PRIVATE_PLATFORM_APIS := true
-LOCAL_INSTRUMENTATION_FOR := MtpDocumentsProvider
-LOCAL_CERTIFICATE := media
-LOCAL_COMPATIBILITY_SUITE += device-tests
-
-include $(BUILD_PACKAGE)
diff --git a/packages/MtpDocumentsProvider/perf_tests/AndroidManifest.xml b/packages/MtpDocumentsProvider/perf_tests/AndroidManifest.xml
deleted file mode 100644
index 4367652..0000000
--- a/packages/MtpDocumentsProvider/perf_tests/AndroidManifest.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.mtp.perftests"
- android:sharedUserId="android.media">
-
- <application>
- <uses-library android:name="android.test.runner" />
- </application>
-
- <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
- android:targetPackage="com.android.mtp"
- android:label="Performance tests for MtpDocumentsProvider." />
-</manifest>
diff --git a/packages/MtpDocumentsProvider/perf_tests/AndroidTest.xml b/packages/MtpDocumentsProvider/perf_tests/AndroidTest.xml
deleted file mode 100644
index 8b7292b..0000000
--- a/packages/MtpDocumentsProvider/perf_tests/AndroidTest.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2018 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<configuration description="Runs MtpDocumentsProviderPerfTests metric instrumentation.">
- <option name="test-suite-tag" value="apct" />
- <option name="test-suite-tag" value="apct-metric-instrumentation" />
- <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
- <option name="cleanup-apks" value="true" />
- <option name="test-file-name" value="MtpDocumentsProviderPerfTests.apk" />
- </target_preparer>
-
- <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
- <option name="package" value="com.android.mtp.perftests" />
- </test>
-</configuration>
diff --git a/packages/MtpDocumentsProvider/perf_tests/src/com/android/mtp/AppFusePerfTest.java b/packages/MtpDocumentsProvider/perf_tests/src/com/android/mtp/AppFusePerfTest.java
deleted file mode 100644
index 58b9c67..0000000
--- a/packages/MtpDocumentsProvider/perf_tests/src/com/android/mtp/AppFusePerfTest.java
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * Copyright (C) 2016 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.mtp;
-
-import android.app.Activity;
-import android.content.Context;
-import android.os.Bundle;
-import android.os.ParcelFileDescriptor;
-import android.os.ProxyFileDescriptorCallback;
-import android.os.storage.StorageManager;
-import android.system.ErrnoException;
-
-import androidx.test.InstrumentationRegistry;
-import androidx.test.filters.LargeTest;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
-
-import java.io.IOException;
-
-@RunWith(JUnit4.class)
-public class AppFusePerfTest {
- final static int SIZE = 10 * 1024 * 1024; // 10MB
-
- @Test
- @LargeTest
- public void testReadWriteFile() throws IOException {
- final Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
- final StorageManager storageManager = context.getSystemService(StorageManager.class);
-
- final byte[] bytes = new byte[SIZE];
- final int SAMPLES = 100;
- final double[] readTime = new double[SAMPLES];
- final double[] writeTime = new double[SAMPLES];
-
- for (int i = 0; i < SAMPLES; i++) {
- final ParcelFileDescriptor fd = storageManager.openProxyFileDescriptor(
- ParcelFileDescriptor.MODE_READ_ONLY, new TestCallback());
- try (final ParcelFileDescriptor.AutoCloseInputStream stream =
- new ParcelFileDescriptor.AutoCloseInputStream(fd)) {
- final long startTime = System.nanoTime();
- stream.read(bytes);
- readTime[i] = (System.nanoTime() - startTime) / 1000.0 / 1000.0;
- }
- }
-
- for (int i = 0; i < SAMPLES; i++) {
- final ParcelFileDescriptor fd = storageManager.openProxyFileDescriptor(
- ParcelFileDescriptor.MODE_WRITE_ONLY | ParcelFileDescriptor.MODE_TRUNCATE,
- new TestCallback());
- try (final ParcelFileDescriptor.AutoCloseOutputStream stream =
- new ParcelFileDescriptor.AutoCloseOutputStream(fd)) {
- final long startTime = System.nanoTime();
- stream.write(bytes);
- writeTime[i] = (System.nanoTime() - startTime) / 1000.0 / 1000.0;
- }
- }
-
- double readAverage = 0;
- double writeAverage = 0;
- double readSquaredAverage = 0;
- double writeSquaredAverage = 0;
- for (int i = 0; i < SAMPLES; i++) {
- readAverage += readTime[i];
- writeAverage += writeTime[i];
- readSquaredAverage += readTime[i] * readTime[i];
- writeSquaredAverage += writeTime[i] * writeTime[i];
- }
-
- readAverage /= SAMPLES;
- writeAverage /= SAMPLES;
- readSquaredAverage /= SAMPLES;
- writeSquaredAverage /= SAMPLES;
-
- final Bundle results = new Bundle();
- results.putDouble("readAverage", readAverage);
- results.putDouble("readStandardDeviation",
- Math.sqrt(readSquaredAverage - readAverage * readAverage));
- results.putDouble("writeAverage", writeAverage);
- results.putDouble("writeStandardDeviation",
- Math.sqrt(writeSquaredAverage - writeAverage * writeAverage));
- InstrumentationRegistry.getInstrumentation().sendStatus(Activity.RESULT_OK, results);
- }
-
- private static class TestCallback extends ProxyFileDescriptorCallback {
- @Override
- public long onGetSize() throws ErrnoException {
- return SIZE;
- }
-
- @Override
- public int onRead(long offset, int size, byte[] data) throws ErrnoException {
- return size;
- }
-
- @Override
- public int onWrite(long offset, int size, byte[] data) throws ErrnoException {
- return size;
- }
-
- @Override
- public void onFsync() throws ErrnoException {}
-
- @Override
- public void onRelease() {}
- }
-}
diff --git a/packages/MtpDocumentsProvider/proguard.flags b/packages/MtpDocumentsProvider/proguard.flags
deleted file mode 100644
index e660121..0000000
--- a/packages/MtpDocumentsProvider/proguard.flags
+++ /dev/null
@@ -1,4 +0,0 @@
-# Keeps methods that are invoked by JNI.
--keepclassmembers class * {
- @com.android.mtp.annotations.UsedByNative *;
-}
diff --git a/packages/MtpDocumentsProvider/res/drawable-hdpi/ic_root_mtp.png b/packages/MtpDocumentsProvider/res/drawable-hdpi/ic_root_mtp.png
deleted file mode 100644
index 7691433..0000000
--- a/packages/MtpDocumentsProvider/res/drawable-hdpi/ic_root_mtp.png
+++ /dev/null
Binary files differ
diff --git a/packages/MtpDocumentsProvider/res/drawable-mdpi/ic_root_mtp.png b/packages/MtpDocumentsProvider/res/drawable-mdpi/ic_root_mtp.png
deleted file mode 100644
index 1cf7b3a..0000000
--- a/packages/MtpDocumentsProvider/res/drawable-mdpi/ic_root_mtp.png
+++ /dev/null
Binary files differ
diff --git a/packages/MtpDocumentsProvider/res/drawable-xhdpi/ic_root_mtp.png b/packages/MtpDocumentsProvider/res/drawable-xhdpi/ic_root_mtp.png
deleted file mode 100644
index 27e3542..0000000
--- a/packages/MtpDocumentsProvider/res/drawable-xhdpi/ic_root_mtp.png
+++ /dev/null
Binary files differ
diff --git a/packages/MtpDocumentsProvider/res/drawable-xxhdpi/ic_root_mtp.png b/packages/MtpDocumentsProvider/res/drawable-xxhdpi/ic_root_mtp.png
deleted file mode 100644
index 3df2578b..0000000
--- a/packages/MtpDocumentsProvider/res/drawable-xxhdpi/ic_root_mtp.png
+++ /dev/null
Binary files differ
diff --git a/packages/MtpDocumentsProvider/res/drawable-xxxhdpi/ic_root_mtp.png b/packages/MtpDocumentsProvider/res/drawable-xxxhdpi/ic_root_mtp.png
deleted file mode 100644
index fd2b795..0000000
--- a/packages/MtpDocumentsProvider/res/drawable-xxxhdpi/ic_root_mtp.png
+++ /dev/null
Binary files differ
diff --git a/packages/MtpDocumentsProvider/res/mipmap-hdpi/ic_launcher_download.png b/packages/MtpDocumentsProvider/res/mipmap-hdpi/ic_launcher_download.png
deleted file mode 100644
index f958bbd..0000000
--- a/packages/MtpDocumentsProvider/res/mipmap-hdpi/ic_launcher_download.png
+++ /dev/null
Binary files differ
diff --git a/packages/MtpDocumentsProvider/res/mipmap-mdpi/ic_launcher_download.png b/packages/MtpDocumentsProvider/res/mipmap-mdpi/ic_launcher_download.png
deleted file mode 100644
index f2e9376..0000000
--- a/packages/MtpDocumentsProvider/res/mipmap-mdpi/ic_launcher_download.png
+++ /dev/null
Binary files differ
diff --git a/packages/MtpDocumentsProvider/res/mipmap-xhdpi/ic_launcher_download.png b/packages/MtpDocumentsProvider/res/mipmap-xhdpi/ic_launcher_download.png
deleted file mode 100644
index 4dc5336..0000000
--- a/packages/MtpDocumentsProvider/res/mipmap-xhdpi/ic_launcher_download.png
+++ /dev/null
Binary files differ
diff --git a/packages/MtpDocumentsProvider/res/mipmap-xxhdpi/ic_launcher_download.png b/packages/MtpDocumentsProvider/res/mipmap-xxhdpi/ic_launcher_download.png
deleted file mode 100644
index 8716290..0000000
--- a/packages/MtpDocumentsProvider/res/mipmap-xxhdpi/ic_launcher_download.png
+++ /dev/null
Binary files differ
diff --git a/packages/MtpDocumentsProvider/res/mipmap-xxxhdpi/ic_launcher_download.png b/packages/MtpDocumentsProvider/res/mipmap-xxxhdpi/ic_launcher_download.png
deleted file mode 100644
index f5be219..0000000
--- a/packages/MtpDocumentsProvider/res/mipmap-xxxhdpi/ic_launcher_download.png
+++ /dev/null
Binary files differ
diff --git a/packages/MtpDocumentsProvider/res/values-af/strings.xml b/packages/MtpDocumentsProvider/res/values-af/strings.xml
deleted file mode 100644
index c2c8761..0000000
--- a/packages/MtpDocumentsProvider/res/values-af/strings.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<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="6271216747302322594">"MTP-gasheer"</string>
- <string name="downloads_app_label" msgid="7120690641874849726">"Aflaaie"</string>
- <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string>
- <string name="accessing_notification_title" msgid="3030133609230917944">"Toegang tot lêers word tans van <xliff:g id="DEVICE_MODEL">%1$s</xliff:g> af verkry"</string>
- <string name="error_busy_device" msgid="3997316850357386589">"Die ander toestel is besig. Jy kan nie lêers oordra voordat dit beskikbaar is nie."</string>
- <string name="error_locked_device" msgid="7557872102188356147">"Geen lêers is gevind nie. Die ander toestel is dalk gesluit. Indien wel, ontsluit dit en probeer weer."</string>
-</resources>
diff --git a/packages/MtpDocumentsProvider/res/values-am/strings.xml b/packages/MtpDocumentsProvider/res/values-am/strings.xml
deleted file mode 100644
index 7b721c8..0000000
--- a/packages/MtpDocumentsProvider/res/values-am/strings.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<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="6271216747302322594">"የMTP አስተናጋጅ"</string>
- <string name="downloads_app_label" msgid="7120690641874849726">"የወረዱ"</string>
- <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string>
- <string name="accessing_notification_title" msgid="3030133609230917944">"ፋይሎችን ከ<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> በመድረስ ላይ"</string>
- <string name="error_busy_device" msgid="3997316850357386589">"ሌላኛው መሣሪያ ሥራ በዝቶበታል። እስከሚገኝ ድረስ ፋይሎችን ማስተላለፍ አይችሉም።"</string>
- <string name="error_locked_device" msgid="7557872102188356147">"ምንም ፋይሎች አልተገኙም። ሌላኛው መሣሪያ ተቆልፎ ሊሆን ይችላል። ተቆልፎ ከሆነ ይክፈቱት እና እንደገና ይሞክሩ።"</string>
-</resources>
diff --git a/packages/MtpDocumentsProvider/res/values-ar/strings.xml b/packages/MtpDocumentsProvider/res/values-ar/strings.xml
deleted file mode 100644
index 284a860..0000000
--- a/packages/MtpDocumentsProvider/res/values-ar/strings.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<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="6271216747302322594">"مضيف بروتوكول نقل الوسائط (MTP)"</string>
- <string name="downloads_app_label" msgid="7120690641874849726">"التنزيلات"</string>
- <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string>
- <string name="accessing_notification_title" msgid="3030133609230917944">"جارٍ الوصول إلى الملفات من <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string>
- <string name="error_busy_device" msgid="3997316850357386589">"الجهاز الآخر مشغول، ولا يمكنك نقل الملفات إلا بعد أن يصبح متاحًا."</string>
- <string name="error_locked_device" msgid="7557872102188356147">"لم يتم العثور على ملفات، وربما يكون الجهاز الآخر في وضع القفل. إذا كان الأمر كذلك، فعليك إلغاء قفله وإعادة المحاولة."</string>
-</resources>
diff --git a/packages/MtpDocumentsProvider/res/values-as/strings.xml b/packages/MtpDocumentsProvider/res/values-as/strings.xml
deleted file mode 100644
index c8bdbd6..0000000
--- a/packages/MtpDocumentsProvider/res/values-as/strings.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<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="6271216747302322594">"এমটিপি হ\'ষ্ট"</string>
- <string name="downloads_app_label" msgid="7120690641874849726">"ডাউনল\'ডসমূহ"</string>
- <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string>
- <string name="accessing_notification_title" msgid="3030133609230917944">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g>ৰ পৰা ফাইলসমূহ চোৱা হৈছে"</string>
- <string name="error_busy_device" msgid="3997316850357386589">"আনটো ডিভাইচ ব্যস্ত হৈ আছে। সেইটো উপলব্ধ নোহোৱালৈকে আপুনি ফাইলসমূহ স্থানান্তৰ কৰিব নোৱাৰে।"</string>
- <string name="error_locked_device" msgid="7557872102188356147">"কোনো ফাইল পোৱা নগ\'ল। আনটো ডিভাইচ লক হৈ থাকিব পাৰে। যদি লক হৈ আছে, তেন্তে আনলক কৰি আকৌ চেষ্টা কৰক।"</string>
-</resources>
diff --git a/packages/MtpDocumentsProvider/res/values-az/strings.xml b/packages/MtpDocumentsProvider/res/values-az/strings.xml
deleted file mode 100644
index e8ed124..0000000
--- a/packages/MtpDocumentsProvider/res/values-az/strings.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<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="6271216747302322594">"MTP Host"</string>
- <string name="downloads_app_label" msgid="7120690641874849726">"Endirmələr"</string>
- <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string>
- <string name="accessing_notification_title" msgid="3030133609230917944">"Fayllara <xliff:g id="DEVICE_MODEL">%1$s</xliff:g> cihazından daxil olunur"</string>
- <string name="error_busy_device" msgid="3997316850357386589">"Digər cihaz məşğuldur. Əlçatan olmayana kimi fayl köçürə bilməzsiniz."</string>
- <string name="error_locked_device" msgid="7557872102188356147">"Fayl tapılmadı. Digər cihaz kilidlənmiş ola bilər. Elədirsə, kiliddən çıxarın və yenidən cəhd edin."</string>
-</resources>
diff --git a/packages/MtpDocumentsProvider/res/values-b+sr+Latn/strings.xml b/packages/MtpDocumentsProvider/res/values-b+sr+Latn/strings.xml
deleted file mode 100644
index bc900996..0000000
--- a/packages/MtpDocumentsProvider/res/values-b+sr+Latn/strings.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<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="6271216747302322594">"MTP host"</string>
- <string name="downloads_app_label" msgid="7120690641874849726">"Preuzimanja"</string>
- <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string>
- <string name="accessing_notification_title" msgid="3030133609230917944">"Pristup datotekama sa uređaja <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string>
- <string name="error_busy_device" msgid="3997316850357386589">"Drugi uređaj je zauzet. Datoteke možete da prenesete tek kad on postane dostupan."</string>
- <string name="error_locked_device" msgid="7557872102188356147">"Nije pronađena nijedna datoteka. Drugi uređaj je možda zaključan. Ako jeste, otključajte ga i pokušajte ponovo."</string>
-</resources>
diff --git a/packages/MtpDocumentsProvider/res/values-be/strings.xml b/packages/MtpDocumentsProvider/res/values-be/strings.xml
deleted file mode 100644
index f6263ac..0000000
--- a/packages/MtpDocumentsProvider/res/values-be/strings.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<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="6271216747302322594">"Вузел MTP"</string>
- <string name="downloads_app_label" msgid="7120690641874849726">"Спампоўкі"</string>
- <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string>
- <string name="accessing_notification_title" msgid="3030133609230917944">"Доступ да файлаў з <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string>
- <string name="error_busy_device" msgid="3997316850357386589">"Іншая прылада занята. Вы не можаце перадаць файлы, пакуль яна не стане даступнай."</string>
- <string name="error_locked_device" msgid="7557872102188356147">"Файлы не знойдзены. Іншая прылада можа быць заблакіравана. Калі гэта так, разблакіруйце яе і паўтарыце спробу."</string>
-</resources>
diff --git a/packages/MtpDocumentsProvider/res/values-bg/strings.xml b/packages/MtpDocumentsProvider/res/values-bg/strings.xml
deleted file mode 100644
index 52d3119..0000000
--- a/packages/MtpDocumentsProvider/res/values-bg/strings.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<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="6271216747302322594">"MTP хост"</string>
- <string name="downloads_app_label" msgid="7120690641874849726">"Изтегляния"</string>
- <string name="root_name" msgid="5819495383921089536">"<xliff:g id="STORAGE_NAME">%2$s</xliff:g> на <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string>
- <string name="accessing_notification_title" msgid="3030133609230917944">"От <xliff:g id="DEVICE_MODEL">%1$s</xliff:g> се осъществява достъп до файловете"</string>
- <string name="error_busy_device" msgid="3997316850357386589">"Другото устройство е заето. Не можете да прехвърляте файлове, докато то не се освободи."</string>
- <string name="error_locked_device" msgid="7557872102188356147">"Няма намерени файлове. Другото устройство може да е заключено. Ако е така, отключете го и опитайте отново."</string>
-</resources>
diff --git a/packages/MtpDocumentsProvider/res/values-bn/strings.xml b/packages/MtpDocumentsProvider/res/values-bn/strings.xml
deleted file mode 100644
index 7fad89e..0000000
--- a/packages/MtpDocumentsProvider/res/values-bn/strings.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<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="6271216747302322594">"MTP হোস্ট"</string>
- <string name="downloads_app_label" msgid="7120690641874849726">"ডাউনলোডগুলি"</string>
- <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string>
- <string name="accessing_notification_title" msgid="3030133609230917944">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> থেকে ফাইলগুলিকে অ্যাক্সেস করা হচ্ছে"</string>
- <string name="error_busy_device" msgid="3997316850357386589">"অন্য ডিভাইসটি ব্যস্ত আছে৷ এটি উপলব্ধ না হওয়া পর্যন্ত আপনি ফাইলগুলিকে স্থানান্তর করতে পারবেন না৷"</string>
- <string name="error_locked_device" msgid="7557872102188356147">"কোনো ফাইল পাওয়া যায়নি৷ অন্য ডিভাইসটি লক থাকতে পারে৷ যদি তাই হয়, তাহলে এটিকে আনলক করে আবার চেষ্টা করুন৷"</string>
-</resources>
diff --git a/packages/MtpDocumentsProvider/res/values-bs/strings.xml b/packages/MtpDocumentsProvider/res/values-bs/strings.xml
deleted file mode 100644
index 18c2363..0000000
--- a/packages/MtpDocumentsProvider/res/values-bs/strings.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<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="6271216747302322594">"MTP Host"</string>
- <string name="downloads_app_label" msgid="7120690641874849726">"Preuzimanja"</string>
- <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string>
- <string name="accessing_notification_title" msgid="3030133609230917944">"Pristupanje fajlovima iz uređaja <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string>
- <string name="error_busy_device" msgid="3997316850357386589">"Drugi uređaj je zauzet. Nećete moći prenositi fajlove dok ne bude dostupan."</string>
- <string name="error_locked_device" msgid="7557872102188356147">"Fajlovi nisu pronađeni. Moguće je da je drugi uređaj zaključan. Ako jeste, otključajte ga i pokušajte ponovo."</string>
-</resources>
diff --git a/packages/MtpDocumentsProvider/res/values-ca/strings.xml b/packages/MtpDocumentsProvider/res/values-ca/strings.xml
deleted file mode 100644
index b2aa599..0000000
--- a/packages/MtpDocumentsProvider/res/values-ca/strings.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<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="6271216747302322594">"Amfitrió MTP"</string>
- <string name="downloads_app_label" msgid="7120690641874849726">"Baixades"</string>
- <string name="root_name" msgid="5819495383921089536">"<xliff:g id="STORAGE_NAME">%2$s</xliff:g> de <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string>
- <string name="accessing_notification_title" msgid="3030133609230917944">"S\'està accedint als fitxers del dispositiu <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string>
- <string name="error_busy_device" msgid="3997316850357386589">"L\'altre dispositiu està ocupat. No pots transferir fitxers fins que estigui disponible."</string>
- <string name="error_locked_device" msgid="7557872102188356147">"No s\'han trobat fitxers. És possible que l\'altre dispositiu estigui bloquejat. Si és així, desbloqueja\'l i torna-ho a provar."</string>
-</resources>
diff --git a/packages/MtpDocumentsProvider/res/values-cs/strings.xml b/packages/MtpDocumentsProvider/res/values-cs/strings.xml
deleted file mode 100644
index 2156e8c..0000000
--- a/packages/MtpDocumentsProvider/res/values-cs/strings.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<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="6271216747302322594">"Hostitel MTP"</string>
- <string name="downloads_app_label" msgid="7120690641874849726">"Stahování"</string>
- <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> – <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string>
- <string name="accessing_notification_title" msgid="3030133609230917944">"Používání souborů ze zařízení <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string>
- <string name="error_busy_device" msgid="3997316850357386589">"Druhé zařízení je zaneprázdněné. Dokud nebude dostupné, soubory nelze přenést."</string>
- <string name="error_locked_device" msgid="7557872102188356147">"Nebyly nalezeny žádné soubory. Druhé zařízení je možná uzamčené. Pokud ano, odemkněte jej a zkuste to znovu."</string>
-</resources>
diff --git a/packages/MtpDocumentsProvider/res/values-da/strings.xml b/packages/MtpDocumentsProvider/res/values-da/strings.xml
deleted file mode 100644
index b82c5e8..0000000
--- a/packages/MtpDocumentsProvider/res/values-da/strings.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<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="6271216747302322594">"MTP-host"</string>
- <string name="downloads_app_label" msgid="7120690641874849726">"Downloads"</string>
- <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string>
- <string name="accessing_notification_title" msgid="3030133609230917944">"Adgang til filer fra <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string>
- <string name="error_busy_device" msgid="3997316850357386589">"Den anden enhed er optaget. Du kan ikke overføre filer, før den er tilgængelig."</string>
- <string name="error_locked_device" msgid="7557872102188356147">"Der blev ikke fundet nogen filer. Den anden enhed er muligvis låst. Hvis dette er tilfældet, skal du låse den op og prøve igen."</string>
-</resources>
diff --git a/packages/MtpDocumentsProvider/res/values-de/strings.xml b/packages/MtpDocumentsProvider/res/values-de/strings.xml
deleted file mode 100644
index 9a71c76..0000000
--- a/packages/MtpDocumentsProvider/res/values-de/strings.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<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="6271216747302322594">"MTP-Host"</string>
- <string name="downloads_app_label" msgid="7120690641874849726">"Downloads"</string>
- <string name="root_name" msgid="5819495383921089536">"<xliff:g id="STORAGE_NAME">%2$s</xliff:g> von <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string>
- <string name="accessing_notification_title" msgid="3030133609230917944">"Zugriff auf Dateien von <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string>
- <string name="error_busy_device" msgid="3997316850357386589">"Das andere Gerät ist nicht verfügbar. Du kannst die Dateien übertragen, sobald das Gerät wieder verfügbar ist."</string>
- <string name="error_locked_device" msgid="7557872102188356147">"Keine Dateien gefunden. Das andere Gerät ist möglicherweise gesperrt. Entsperre es in diesem Fall und versuche es noch einmal."</string>
-</resources>
diff --git a/packages/MtpDocumentsProvider/res/values-el/strings.xml b/packages/MtpDocumentsProvider/res/values-el/strings.xml
deleted file mode 100644
index 562d295..0000000
--- a/packages/MtpDocumentsProvider/res/values-el/strings.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<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="6271216747302322594">"Κεντρικός υπολογιστής MTP"</string>
- <string name="downloads_app_label" msgid="7120690641874849726">"Λήψεις"</string>
- <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string>
- <string name="accessing_notification_title" msgid="3030133609230917944">"Πρόσβαση στα αρχεία από τη συσκευή <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string>
- <string name="error_busy_device" msgid="3997316850357386589">"Η άλλη συσκευή είναι απασχολημένη. Δεν μπορείτε να μεταφέρετε αρχεία μέχρι να γίνει διαθέσιμη."</string>
- <string name="error_locked_device" msgid="7557872102188356147">"Δεν βρέθηκαν αρχεία. Η άλλη συσκευή ενδέχεται να είναι κλειδωμένη. Εάν ισχύει αυτό, ξεκλειδώστε την και δοκιμάστε ξανά."</string>
-</resources>
diff --git a/packages/MtpDocumentsProvider/res/values-en-rAU/strings.xml b/packages/MtpDocumentsProvider/res/values-en-rAU/strings.xml
deleted file mode 100644
index 5f2167e..0000000
--- a/packages/MtpDocumentsProvider/res/values-en-rAU/strings.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<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="6271216747302322594">"MTP Host"</string>
- <string name="downloads_app_label" msgid="7120690641874849726">"Downloads"</string>
- <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string>
- <string name="accessing_notification_title" msgid="3030133609230917944">"Accessing files from <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string>
- <string name="error_busy_device" msgid="3997316850357386589">"The other device is busy. You can\'t transfer files until it\'s available."</string>
- <string name="error_locked_device" msgid="7557872102188356147">"No files found. The other device may be locked. If so, unlock it and try again."</string>
-</resources>
diff --git a/packages/MtpDocumentsProvider/res/values-en-rCA/strings.xml b/packages/MtpDocumentsProvider/res/values-en-rCA/strings.xml
deleted file mode 100644
index 5f2167e..0000000
--- a/packages/MtpDocumentsProvider/res/values-en-rCA/strings.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<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="6271216747302322594">"MTP Host"</string>
- <string name="downloads_app_label" msgid="7120690641874849726">"Downloads"</string>
- <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string>
- <string name="accessing_notification_title" msgid="3030133609230917944">"Accessing files from <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string>
- <string name="error_busy_device" msgid="3997316850357386589">"The other device is busy. You can\'t transfer files until it\'s available."</string>
- <string name="error_locked_device" msgid="7557872102188356147">"No files found. The other device may be locked. If so, unlock it and try again."</string>
-</resources>
diff --git a/packages/MtpDocumentsProvider/res/values-en-rGB/strings.xml b/packages/MtpDocumentsProvider/res/values-en-rGB/strings.xml
deleted file mode 100644
index 5f2167e..0000000
--- a/packages/MtpDocumentsProvider/res/values-en-rGB/strings.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<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="6271216747302322594">"MTP Host"</string>
- <string name="downloads_app_label" msgid="7120690641874849726">"Downloads"</string>
- <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string>
- <string name="accessing_notification_title" msgid="3030133609230917944">"Accessing files from <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string>
- <string name="error_busy_device" msgid="3997316850357386589">"The other device is busy. You can\'t transfer files until it\'s available."</string>
- <string name="error_locked_device" msgid="7557872102188356147">"No files found. The other device may be locked. If so, unlock it and try again."</string>
-</resources>
diff --git a/packages/MtpDocumentsProvider/res/values-en-rIN/strings.xml b/packages/MtpDocumentsProvider/res/values-en-rIN/strings.xml
deleted file mode 100644
index 5f2167e..0000000
--- a/packages/MtpDocumentsProvider/res/values-en-rIN/strings.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<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="6271216747302322594">"MTP Host"</string>
- <string name="downloads_app_label" msgid="7120690641874849726">"Downloads"</string>
- <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string>
- <string name="accessing_notification_title" msgid="3030133609230917944">"Accessing files from <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string>
- <string name="error_busy_device" msgid="3997316850357386589">"The other device is busy. You can\'t transfer files until it\'s available."</string>
- <string name="error_locked_device" msgid="7557872102188356147">"No files found. The other device may be locked. If so, unlock it and try again."</string>
-</resources>
diff --git a/packages/MtpDocumentsProvider/res/values-en-rXC/strings.xml b/packages/MtpDocumentsProvider/res/values-en-rXC/strings.xml
deleted file mode 100644
index e968a55..0000000
--- a/packages/MtpDocumentsProvider/res/values-en-rXC/strings.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<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="6271216747302322594">"MTP Host"</string>
- <string name="downloads_app_label" msgid="7120690641874849726">"Downloads"</string>
- <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string>
- <string name="accessing_notification_title" msgid="3030133609230917944">"Accessing files from <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string>
- <string name="error_busy_device" msgid="3997316850357386589">"The other device is busy. You can\'t transfer files until it\'s available."</string>
- <string name="error_locked_device" msgid="7557872102188356147">"No files found. The other device may be locked. If so, unlock it and try again."</string>
-</resources>
diff --git a/packages/MtpDocumentsProvider/res/values-es-rUS/strings.xml b/packages/MtpDocumentsProvider/res/values-es-rUS/strings.xml
deleted file mode 100644
index 740d224..0000000
--- a/packages/MtpDocumentsProvider/res/values-es-rUS/strings.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<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="6271216747302322594">"Host MTP"</string>
- <string name="downloads_app_label" msgid="7120690641874849726">"Descargas"</string>
- <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string>
- <string name="accessing_notification_title" msgid="3030133609230917944">"Accediendo a los archivos de <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string>
- <string name="error_busy_device" msgid="3997316850357386589">"El otro dispositivo está ocupado. No podrás transferir archivos hasta que esté disponible."</string>
- <string name="error_locked_device" msgid="7557872102188356147">"No se encontraron archivos. Es posible que el otro dispositivo esté bloqueado. Si es así, desbloquéalo y vuelve a intentarlo."</string>
-</resources>
diff --git a/packages/MtpDocumentsProvider/res/values-es/strings.xml b/packages/MtpDocumentsProvider/res/values-es/strings.xml
deleted file mode 100644
index d80a75a..0000000
--- a/packages/MtpDocumentsProvider/res/values-es/strings.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<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="6271216747302322594">"Host de MTP"</string>
- <string name="downloads_app_label" msgid="7120690641874849726">"Descargas"</string>
- <string name="root_name" msgid="5819495383921089536">"<xliff:g id="STORAGE_NAME">%2$s</xliff:g> de <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string>
- <string name="accessing_notification_title" msgid="3030133609230917944">"Accediendo a los archivos desde <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string>
- <string name="error_busy_device" msgid="3997316850357386589">"El otro dispositivo está ocupado. No se pueden transferir archivos hasta que esté disponible."</string>
- <string name="error_locked_device" msgid="7557872102188356147">"No se ha encontrado ningún archivo. Es posible que el otro dispositivo esté bloqueado. Si es así, desbloquéalo y vuelve a intentarlo."</string>
-</resources>
diff --git a/packages/MtpDocumentsProvider/res/values-et/strings.xml b/packages/MtpDocumentsProvider/res/values-et/strings.xml
deleted file mode 100644
index 7568777..0000000
--- a/packages/MtpDocumentsProvider/res/values-et/strings.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<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="6271216747302322594">"MTP host"</string>
- <string name="downloads_app_label" msgid="7120690641874849726">"Allalaadimised"</string>
- <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g>, <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string>
- <string name="accessing_notification_title" msgid="3030133609230917944">"Juurdepääsemine failidele seadmest <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string>
- <string name="error_busy_device" msgid="3997316850357386589">"Teine seade on hõivatud. Te ei saa faile üle viia enne, kui see seade on saadaval."</string>
- <string name="error_locked_device" msgid="7557872102188356147">"Faile ei leitud. Teine seade võib olla lukustatud. Kui see on nii, avage see ja proovige uuesti."</string>
-</resources>
diff --git a/packages/MtpDocumentsProvider/res/values-eu/strings.xml b/packages/MtpDocumentsProvider/res/values-eu/strings.xml
deleted file mode 100644
index dc9d463..0000000
--- a/packages/MtpDocumentsProvider/res/values-eu/strings.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<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="6271216747302322594">"MTP ostalaria"</string>
- <string name="downloads_app_label" msgid="7120690641874849726">"Deskargak"</string>
- <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string>
- <string name="accessing_notification_title" msgid="3030133609230917944">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> gailuko fitxategiak atzitzen"</string>
- <string name="error_busy_device" msgid="3997316850357386589">"Beste gailua lanpetuta dago. Erabilgarri egon arte ezingo duzu transferitu fitxategirik."</string>
- <string name="error_locked_device" msgid="7557872102188356147">"Ez da aurkitu fitxategirik. Baliteke beste gailua blokeatuta egotea. Hala bada, desblokea ezazu eta saiatu berriro."</string>
-</resources>
diff --git a/packages/MtpDocumentsProvider/res/values-fa/strings.xml b/packages/MtpDocumentsProvider/res/values-fa/strings.xml
deleted file mode 100644
index 9ac58c7..0000000
--- a/packages/MtpDocumentsProvider/res/values-fa/strings.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<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="6271216747302322594">"میزبان MTP"</string>
- <string name="downloads_app_label" msgid="7120690641874849726">"بارگیریها"</string>
- <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string>
- <string name="accessing_notification_title" msgid="3030133609230917944">"دسترسی به فایلها از <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string>
- <string name="error_busy_device" msgid="3997316850357386589">"دستگاه دیگر مشغول است. تا زمانی که این دستگاه دردسترس قرار نگیرد نمیتوانید فایلها را منتقل کنید."</string>
- <string name="error_locked_device" msgid="7557872102188356147">"فایلی پیدا نشد. دستگاه دیگر ممکن است قفل باشد. اگر اینطور است، قفل آن را باز کنید و دوباره تلاش کنید."</string>
-</resources>
diff --git a/packages/MtpDocumentsProvider/res/values-fi/strings.xml b/packages/MtpDocumentsProvider/res/values-fi/strings.xml
deleted file mode 100644
index 0a61d08..0000000
--- a/packages/MtpDocumentsProvider/res/values-fi/strings.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<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="6271216747302322594">"MTP-isäntä"</string>
- <string name="downloads_app_label" msgid="7120690641874849726">"Lataukset"</string>
- <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string>
- <string name="accessing_notification_title" msgid="3030133609230917944">"Käytetään laitteen <xliff:g id="DEVICE_MODEL">%1$s</xliff:g> tiedostoja"</string>
- <string name="error_busy_device" msgid="3997316850357386589">"Toinen laite on varattu. Et voi siirtää tiedostoja, ennen kuin se on käytettävissä."</string>
- <string name="error_locked_device" msgid="7557872102188356147">"Tiedostoja ei löytynyt. Toinen laite voi olla lukittu. Jos näin on, avaa se ja yritä uudelleen."</string>
-</resources>
diff --git a/packages/MtpDocumentsProvider/res/values-fr-rCA/strings.xml b/packages/MtpDocumentsProvider/res/values-fr-rCA/strings.xml
deleted file mode 100644
index 281760e..0000000
--- a/packages/MtpDocumentsProvider/res/values-fr-rCA/strings.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<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="6271216747302322594">"Hôte MTP"</string>
- <string name="downloads_app_label" msgid="7120690641874849726">"Téléchargements"</string>
- <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string>
- <string name="accessing_notification_title" msgid="3030133609230917944">"Accès aux fichiers à partir de l\'appareil <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string>
- <string name="error_busy_device" msgid="3997316850357386589">"L\'autre appareil est occupé. Vous devez attendre qu\'il soit disponible pour transférer des fichiers."</string>
- <string name="error_locked_device" msgid="7557872102188356147">"Aucun fichier trouvé. L\'autre appareil est peut-être verrouillé. Si c\'est le cas, déverrouillez-le, puis réessayez."</string>
-</resources>
diff --git a/packages/MtpDocumentsProvider/res/values-fr/strings.xml b/packages/MtpDocumentsProvider/res/values-fr/strings.xml
deleted file mode 100644
index 96c713b..0000000
--- a/packages/MtpDocumentsProvider/res/values-fr/strings.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<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="6271216747302322594">"Hôte MTP"</string>
- <string name="downloads_app_label" msgid="7120690641874849726">"Téléchargements"</string>
- <string name="root_name" msgid="5819495383921089536">"<xliff:g id="STORAGE_NAME">%2$s</xliff:g> – <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string>
- <string name="accessing_notification_title" msgid="3030133609230917944">"Accès aux fichiers depuis le <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>…"</string>
- <string name="error_busy_device" msgid="3997316850357386589">"L\'autre appareil est occupé. Vous devez attendre qu\'il soit disponible pour transférer des fichiers."</string>
- <string name="error_locked_device" msgid="7557872102188356147">"Aucun fichier trouvé. L\'autre appareil est peut-être verrouillé. Si tel est le cas, déverrouillez-le, puis réessayez."</string>
-</resources>
diff --git a/packages/MtpDocumentsProvider/res/values-gl/strings.xml b/packages/MtpDocumentsProvider/res/values-gl/strings.xml
deleted file mode 100644
index 7e61c7c..0000000
--- a/packages/MtpDocumentsProvider/res/values-gl/strings.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<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="6271216747302322594">"Host MTP"</string>
- <string name="downloads_app_label" msgid="7120690641874849726">"Descargas"</string>
- <string name="root_name" msgid="5819495383921089536">"<xliff:g id="STORAGE_NAME">%2$s</xliff:g> de <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string>
- <string name="accessing_notification_title" msgid="3030133609230917944">"Accedendo aos ficheiros do dispositivo <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string>
- <string name="error_busy_device" msgid="3997316850357386589">"O outro dispositivo está ocupado. Non podes transferir ficheiros ata que estea dispoñible."</string>
- <string name="error_locked_device" msgid="7557872102188356147">"Non se atopou ningún ficheiro. Se o outro dispositivo está bloqueado, desbloquéao e téntao de novo."</string>
-</resources>
diff --git a/packages/MtpDocumentsProvider/res/values-gu/strings.xml b/packages/MtpDocumentsProvider/res/values-gu/strings.xml
deleted file mode 100644
index 468bd9d..0000000
--- a/packages/MtpDocumentsProvider/res/values-gu/strings.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<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="6271216747302322594">"MTP હોસ્ટ"</string>
- <string name="downloads_app_label" msgid="7120690641874849726">"ડાઉનલોડ્સ"</string>
- <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string>
- <string name="accessing_notification_title" msgid="3030133609230917944">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> ની ફાઇલોને ઍક્સેસ કરી રહ્યાં છે"</string>
- <string name="error_busy_device" msgid="3997316850357386589">"અન્ય ઉપકરણ વ્યસ્ત છે. તે ઉપલબ્ધ ન થાય ત્યાં સુધી તમે ફાઇલોને ટ્રાન્સફર કરી શકતાં નથી."</string>
- <string name="error_locked_device" msgid="7557872102188356147">"કોઈ ફાઇલો મળી નહીં. અન્ય ઉપકરણ લૉક કરેલ હોઈ શકે છે. જો આમ હોય, તો તેને અનલૉક કરો અને ફરી પ્રયાસ કરો."</string>
-</resources>
diff --git a/packages/MtpDocumentsProvider/res/values-hi/strings.xml b/packages/MtpDocumentsProvider/res/values-hi/strings.xml
deleted file mode 100644
index e469fc0..0000000
--- a/packages/MtpDocumentsProvider/res/values-hi/strings.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<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="6271216747302322594">"MTP होस्ट"</string>
- <string name="downloads_app_label" msgid="7120690641874849726">"डाउनलोड"</string>
- <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string>
- <string name="accessing_notification_title" msgid="3030133609230917944">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> से फ़ाइलें ऐक्सेस कर रहा है"</string>
- <string name="error_busy_device" msgid="3997316850357386589">"दूसरा डिवाइस व्यस्त है. आप उसके उपलब्ध हो जाने तक फ़ाइलें ट्रांसफ़र नहीं कर सकते."</string>
- <string name="error_locked_device" msgid="7557872102188356147">"कोई फ़ाइल नहीं मिली. हो सकता है कि दूसरा डिवाइस लॉक हो. अगर ऐसा है, तो उसे अनलॉक करें और दोबारा कोशिश करें."</string>
-</resources>
diff --git a/packages/MtpDocumentsProvider/res/values-hr/strings.xml b/packages/MtpDocumentsProvider/res/values-hr/strings.xml
deleted file mode 100644
index 63fc5c7..0000000
--- a/packages/MtpDocumentsProvider/res/values-hr/strings.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<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="6271216747302322594">"MTP host"</string>
- <string name="downloads_app_label" msgid="7120690641874849726">"Preuzimanja"</string>
- <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g><xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string>
- <string name="accessing_notification_title" msgid="3030133609230917944">"Pristupanje datotekama s uređaja <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string>
- <string name="error_busy_device" msgid="3997316850357386589">"Drugi je uređaj zauzet. Datoteke ćete moći prenijeti kada postane dostupan."</string>
- <string name="error_locked_device" msgid="7557872102188356147">"Datoteke nisu pronađene. Drugi je uređaj možda zaključan. U tom ga slučaju otključajte i pokušajte ponovo."</string>
-</resources>
diff --git a/packages/MtpDocumentsProvider/res/values-hu/strings.xml b/packages/MtpDocumentsProvider/res/values-hu/strings.xml
deleted file mode 100644
index e5b822c..0000000
--- a/packages/MtpDocumentsProvider/res/values-hu/strings.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<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="6271216747302322594">"MTP Host"</string>
- <string name="downloads_app_label" msgid="7120690641874849726">"Letöltések"</string>
- <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string>
- <string name="accessing_notification_title" msgid="3030133609230917944">"Hozzáférés a fájlokhoz a következő eszközről: <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string>
- <string name="error_busy_device" msgid="3997316850357386589">"A másik eszköz elfoglalt. Nem vihetők át fájlok addig, amíg rendelkezésre nem áll."</string>
- <string name="error_locked_device" msgid="7557872102188356147">"Nem található fájl. Lehet, hogy a másik eszköz zárolva van. Ha igen, oldja fel, és próbálkozzon újra."</string>
-</resources>
diff --git a/packages/MtpDocumentsProvider/res/values-hy/strings.xml b/packages/MtpDocumentsProvider/res/values-hy/strings.xml
deleted file mode 100644
index 3a6bfb5..0000000
--- a/packages/MtpDocumentsProvider/res/values-hy/strings.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<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="6271216747302322594">"MTP խնամորդ"</string>
- <string name="downloads_app_label" msgid="7120690641874849726">"Ներբեռնումներ"</string>
- <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string>
- <string name="accessing_notification_title" msgid="3030133609230917944">"Մուտք է գործում ֆայլեր <xliff:g id="DEVICE_MODEL">%1$s</xliff:g> սարքից"</string>
- <string name="error_busy_device" msgid="3997316850357386589">"Մյուս սարքը զբաղված է: Ֆայլերը կարող եք փոխանցել միայն երբ այն հասանելի է:"</string>
- <string name="error_locked_device" msgid="7557872102188356147">"Ֆայլեր չեն գտնվել: Հնարավոր է, որ մյուս սարքը կողպված է: Եթե դա այդպես է, ապակողպեք այն և փորձեք նորից:"</string>
-</resources>
diff --git a/packages/MtpDocumentsProvider/res/values-in/strings.xml b/packages/MtpDocumentsProvider/res/values-in/strings.xml
deleted file mode 100644
index 6f65337..0000000
--- a/packages/MtpDocumentsProvider/res/values-in/strings.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<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="6271216747302322594">"Host MTP"</string>
- <string name="downloads_app_label" msgid="7120690641874849726">"Download"</string>
- <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string>
- <string name="accessing_notification_title" msgid="3030133609230917944">"Mengakses file dari <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string>
- <string name="error_busy_device" msgid="3997316850357386589">"Perangkat lainnya sedang sibuk. Anda dapat mentransfer file jika telah tersedia."</string>
- <string name="error_locked_device" msgid="7557872102188356147">"File tidak ditemukan. Perangkat lainnya mungkin terkunci. Jika begitu, buka kuncinya dan coba lagi."</string>
-</resources>
diff --git a/packages/MtpDocumentsProvider/res/values-is/strings.xml b/packages/MtpDocumentsProvider/res/values-is/strings.xml
deleted file mode 100644
index 9388f7e..0000000
--- a/packages/MtpDocumentsProvider/res/values-is/strings.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<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="6271216747302322594">"MTP-hýsill"</string>
- <string name="downloads_app_label" msgid="7120690641874849726">"Niðurhal"</string>
- <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string>
- <string name="accessing_notification_title" msgid="3030133609230917944">"Fær aðgang að skrám frá <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string>
- <string name="error_busy_device" msgid="3997316850357386589">"Hitt tækið er upptekið. Þú getur ekki fært skrár fyrr en það er tiltækt."</string>
- <string name="error_locked_device" msgid="7557872102188356147">"Engar skrár fundust. Hitt tækið gæti verið læst. Ef svo er skaltu opna það og reyna aftur."</string>
-</resources>
diff --git a/packages/MtpDocumentsProvider/res/values-it/strings.xml b/packages/MtpDocumentsProvider/res/values-it/strings.xml
deleted file mode 100644
index a41699f..0000000
--- a/packages/MtpDocumentsProvider/res/values-it/strings.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<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="6271216747302322594">"Host MTP"</string>
- <string name="downloads_app_label" msgid="7120690641874849726">"Download"</string>
- <string name="root_name" msgid="5819495383921089536">"<xliff:g id="STORAGE_NAME">%2$s</xliff:g> di <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string>
- <string name="accessing_notification_title" msgid="3030133609230917944">"Accesso ai file da <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string>
- <string name="error_busy_device" msgid="3997316850357386589">"L\'altro dispositivo è occupato. I file non possono essere trasferiti fino a quando non sarà disponibile."</string>
- <string name="error_locked_device" msgid="7557872102188356147">"Nessun file trovato. L\'altro dispositivo potrebbe essere bloccato. In questo caso, sbloccalo e riprova."</string>
-</resources>
diff --git a/packages/MtpDocumentsProvider/res/values-iw/strings.xml b/packages/MtpDocumentsProvider/res/values-iw/strings.xml
deleted file mode 100644
index 62dfe7d..0000000
--- a/packages/MtpDocumentsProvider/res/values-iw/strings.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<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="6271216747302322594">"מארח פרוטוקול העברת מדיה (MTP)"</string>
- <string name="downloads_app_label" msgid="7120690641874849726">"הורדות"</string>
- <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string>
- <string name="accessing_notification_title" msgid="3030133609230917944">"גישה לקבצים מ-<xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string>
- <string name="error_busy_device" msgid="3997316850357386589">"המכשיר השני לא פנוי. ניתן יהיה להעביר קבצים רק לאחר שהוא יהיה זמין."</string>
- <string name="error_locked_device" msgid="7557872102188356147">"לא נמצאו קבצים. ייתכן שהמכשיר השני נעול. אם כן, פתח אותו ונסה שוב."</string>
-</resources>
diff --git a/packages/MtpDocumentsProvider/res/values-ja/strings.xml b/packages/MtpDocumentsProvider/res/values-ja/strings.xml
deleted file mode 100644
index 72ab33d..0000000
--- a/packages/MtpDocumentsProvider/res/values-ja/strings.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<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="6271216747302322594">"MTP ホスト"</string>
- <string name="downloads_app_label" msgid="7120690641874849726">"ダウンロード"</string>
- <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string>
- <string name="accessing_notification_title" msgid="3030133609230917944">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> からファイルにアクセスしています"</string>
- <string name="error_busy_device" msgid="3997316850357386589">"接続先のデバイスは使用中のため、利用できるようになるまでファイルを転送できません。"</string>
- <string name="error_locked_device" msgid="7557872102188356147">"ファイルが見つかりません。接続先のデバイスがロックされている可能性があります。その場合は、ロックを解除してからもう一度お試しください。"</string>
-</resources>
diff --git a/packages/MtpDocumentsProvider/res/values-ka/strings.xml b/packages/MtpDocumentsProvider/res/values-ka/strings.xml
deleted file mode 100644
index 33812df..0000000
--- a/packages/MtpDocumentsProvider/res/values-ka/strings.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<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="6271216747302322594">"MTP ჰოსტი"</string>
- <string name="downloads_app_label" msgid="7120690641874849726">"ჩამოტვირთვები"</string>
- <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string>
- <string name="accessing_notification_title" msgid="3030133609230917944">"მიმდინარეობს <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>-ზე არსებულ ფაილებზე წვდომა"</string>
- <string name="error_busy_device" msgid="3997316850357386589">"სხვა მოწყობილობა დაკავებულია. ფაილების გადატანა ვერ მოხერხდება, სანამ ის ხელმისაწვდომი არ გახდება."</string>
- <string name="error_locked_device" msgid="7557872102188356147">"ფაილები ვერ მოიძებნა. მეორე მოწყობილობა შეიძლება დაბლოკილი იყოს. ამ შემთხვევაში, განბლოკეთ ის და ცადეთ ხელახლა."</string>
-</resources>
diff --git a/packages/MtpDocumentsProvider/res/values-kk/strings.xml b/packages/MtpDocumentsProvider/res/values-kk/strings.xml
deleted file mode 100644
index a6dea5b..0000000
--- a/packages/MtpDocumentsProvider/res/values-kk/strings.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<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="6271216747302322594">"MTP хосты"</string>
- <string name="downloads_app_label" msgid="7120690641874849726">"Жүктеп алынғандар"</string>
- <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string>
- <string name="accessing_notification_title" msgid="3030133609230917944">"Файлдарға <xliff:g id="DEVICE_MODEL">%1$s</xliff:g> құрылғысынан кіру"</string>
- <string name="error_busy_device" msgid="3997316850357386589">"Екінші құрылғы бос емес. Ол босамайынша, файлдар тасымалданбайды."</string>
- <string name="error_locked_device" msgid="7557872102188356147">"Ешқандай файл табылмады. Екінші құрылғы құлыптаулы болуы мүмкін. Құлыптаулы болса, құлпын ашып, қайталап көріңіз."</string>
-</resources>
diff --git a/packages/MtpDocumentsProvider/res/values-km/strings.xml b/packages/MtpDocumentsProvider/res/values-km/strings.xml
deleted file mode 100644
index baffa95..0000000
--- a/packages/MtpDocumentsProvider/res/values-km/strings.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<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="6271216747302322594">"ម៉ាស៊ីន MTP"</string>
- <string name="downloads_app_label" msgid="7120690641874849726">"ដោយឡូត"</string>
- <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string>
- <string name="accessing_notification_title" msgid="3030133609230917944">"កំពុងចូលដំណើរការពី <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string>
- <string name="error_busy_device" msgid="3997316850357386589">"ឧបករណ៍ផ្សេងទៀតកំពុងជាប់រវល់។ អ្នកមិនផ្ទេរឯកសារបានទេ រហូតទាល់តែវាអាចប្រើបាន។"</string>
- <string name="error_locked_device" msgid="7557872102188356147">"រកមិនឃើញឯកសារទេ។ ឧបករណ៍ផ្សេងទៀតប្រហែលជាត្រូវបានចាក់សោ។ ប្រសិនបើវាត្រូវបានចាក់សោមែន សូមដោះសោ ហើយព្យាយាមម្តងទៀត។"</string>
-</resources>
diff --git a/packages/MtpDocumentsProvider/res/values-kn/strings.xml b/packages/MtpDocumentsProvider/res/values-kn/strings.xml
deleted file mode 100644
index 3f16c14..0000000
--- a/packages/MtpDocumentsProvider/res/values-kn/strings.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<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="6271216747302322594">"MTP ಹೋಸ್ಟ್"</string>
- <string name="downloads_app_label" msgid="7120690641874849726">"ಡೌನ್ಲೋಡ್ಗಳು"</string>
- <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string>
- <string name="accessing_notification_title" msgid="3030133609230917944">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> ನಿಂದ ಫೈಲ್ಗಳನ್ನು ಪ್ರವೇಶಿಸಲಾಗುತ್ತಿದೆ"</string>
- <string name="error_busy_device" msgid="3997316850357386589">"ಬೇರೆಯ ಸಾಧನವು ಕಾರ್ಯನಿರತವಾಗಿದೆ. ಇದು ಲಭ್ಯವಾಗುವವರೆಗೆ ಫೈಲ್ಗಳನ್ನು ನಿಮಗೆ ವರ್ಗಾಯಿಸಲು ಸಾಧ್ಯವಾಗುವುದಿಲ್ಲ."</string>
- <string name="error_locked_device" msgid="7557872102188356147">"ಯಾವುದೇ ಫೈಲ್ಗಳು ಕಂಡುಬಂದಿಲ್ಲ. ಬೇರೆಯ ಸಾಧನವು ಲಾಕ್ ಆಗಿರಬಹುದು. ಹಾಗಾದಲ್ಲಿ, ಇದನ್ನು ಅನ್ಲಾಕ್ ಮಾಡಿ ಹಾಗೂ ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ."</string>
-</resources>
diff --git a/packages/MtpDocumentsProvider/res/values-ko/strings.xml b/packages/MtpDocumentsProvider/res/values-ko/strings.xml
deleted file mode 100644
index bbe2fe6..0000000
--- a/packages/MtpDocumentsProvider/res/values-ko/strings.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<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="6271216747302322594">"MTP 호스트"</string>
- <string name="downloads_app_label" msgid="7120690641874849726">"다운로드"</string>
- <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string>
- <string name="accessing_notification_title" msgid="3030133609230917944">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g>에서 파일에 액세스 중"</string>
- <string name="error_busy_device" msgid="3997316850357386589">"다른 기기가 사용 중입니다. 다른 기기를 사용할 수 있을 때까지 파일을 전송할 수 없습니다."</string>
- <string name="error_locked_device" msgid="7557872102188356147">"파일이 없습니다. 다른 기기가 잠겨 있을 수 있습니다. 기기의 잠금을 해제하고 다시 시도하세요."</string>
-</resources>
diff --git a/packages/MtpDocumentsProvider/res/values-ky/strings.xml b/packages/MtpDocumentsProvider/res/values-ky/strings.xml
deleted file mode 100644
index e60a494..0000000
--- a/packages/MtpDocumentsProvider/res/values-ky/strings.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<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="6271216747302322594">"MTP хосту"</string>
- <string name="downloads_app_label" msgid="7120690641874849726">"Жүктөлүп алынган нерселер"</string>
- <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string>
- <string name="accessing_notification_title" msgid="3030133609230917944">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> түзмөгүндөгү файлдар колдонулууда"</string>
- <string name="error_busy_device" msgid="3997316850357386589">"Берки түзмөк бош эмес. Ал бошомоюнча файлдарды өткөрө албайсыз."</string>
- <string name="error_locked_device" msgid="7557872102188356147">"Бир дагы файл табылган жок. Берки түзмөк кулпуланып турат окшойт. Кулпусун ачып, кайра аракет кылып көрүңүз."</string>
-</resources>
diff --git a/packages/MtpDocumentsProvider/res/values-lo/strings.xml b/packages/MtpDocumentsProvider/res/values-lo/strings.xml
deleted file mode 100644
index bcc0ee6..0000000
--- a/packages/MtpDocumentsProvider/res/values-lo/strings.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<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="6271216747302322594">"ໂຮສ MTP"</string>
- <string name="downloads_app_label" msgid="7120690641874849726">"ການດາວໂຫລດ"</string>
- <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string>
- <string name="accessing_notification_title" msgid="3030133609230917944">"ກຳລັງເຂົ້າເຖິງໄຟລ໌ຈາກ <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string>
- <string name="error_busy_device" msgid="3997316850357386589">"ອຸປະກອນອື່ນບໍ່ຫວ່າງເທື່ອ. ທ່ານບໍ່ສາມາດໂອນຍ້າຍໄຟລ໌ໄດ້ຈົນກວ່າມັນຈະຫວ່າງ."</string>
- <string name="error_locked_device" msgid="7557872102188356147">"ບໍ່ພົບໄຟລ໌. ອຸປະກອນອີກເຄື່ອງອາດຖືກລັອກໄວ້ຢູ່. ຫາກມັນຖືກລັອກໄວ້, ໃຫ້ປົດລັອກມັນກ່ອນແລ້ວລອງໃໝ່ອີກຄັ້ງ."</string>
-</resources>
diff --git a/packages/MtpDocumentsProvider/res/values-lt/strings.xml b/packages/MtpDocumentsProvider/res/values-lt/strings.xml
deleted file mode 100644
index 8bff3a8..0000000
--- a/packages/MtpDocumentsProvider/res/values-lt/strings.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<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="6271216747302322594">"MPP priegloba"</string>
- <string name="downloads_app_label" msgid="7120690641874849726">"Atsisiuntimai"</string>
- <string name="root_name" msgid="5819495383921089536">"„<xliff:g id="DEVICE_MODEL">%1$s</xliff:g>“ <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string>
- <string name="accessing_notification_title" msgid="3030133609230917944">"Pasiekiami failai iš „<xliff:g id="DEVICE_MODEL">%1$s</xliff:g>“"</string>
- <string name="error_busy_device" msgid="3997316850357386589">"Kitas įrenginys yra užsiėmęs. Failus galėsite perkelti tik tada, kai jis bus pasiekiamas."</string>
- <string name="error_locked_device" msgid="7557872102188356147">"Nerasta failų. Gali būti, kad kitas įrenginys yra užrakintas. Jei taip yra, atrakinkite jį ir bandykite dar kartą."</string>
-</resources>
diff --git a/packages/MtpDocumentsProvider/res/values-lv/strings.xml b/packages/MtpDocumentsProvider/res/values-lv/strings.xml
deleted file mode 100644
index 5e96338..0000000
--- a/packages/MtpDocumentsProvider/res/values-lv/strings.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<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="6271216747302322594">"MTP saimniekdators"</string>
- <string name="downloads_app_label" msgid="7120690641874849726">"Lejupielādes"</string>
- <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string>
- <string name="accessing_notification_title" msgid="3030133609230917944">"Piekļuve failiem no: <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string>
- <string name="error_busy_device" msgid="3997316850357386589">"Otra ierīce ir aizņemta. Varēsiet pārsūtīt failus tikai tad, kad tā būs pieejama."</string>
- <string name="error_locked_device" msgid="7557872102188356147">"Neviens fails netika atrasts. Iespējams, otra ierīce ir bloķēta. Ja tā ir, atbloķējiet ierīci un mēģiniet vēlreiz."</string>
-</resources>
diff --git a/packages/MtpDocumentsProvider/res/values-mk/strings.xml b/packages/MtpDocumentsProvider/res/values-mk/strings.xml
deleted file mode 100644
index 6028b71..0000000
--- a/packages/MtpDocumentsProvider/res/values-mk/strings.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<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="6271216747302322594">"MTP-хост"</string>
- <string name="downloads_app_label" msgid="7120690641874849726">"Преземања"</string>
- <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string>
- <string name="accessing_notification_title" msgid="3030133609230917944">"Се пристапува до датотеки од <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string>
- <string name="error_busy_device" msgid="3997316850357386589">"Другиот уред е зафатен. Не може да се пренесуваат датотеки сѐ додека не стане достапен."</string>
- <string name="error_locked_device" msgid="7557872102188356147">"Не се најдени датотеки. Другиот уред можеби е заклучен. Ако е така, отклучете го и обидете се повторно."</string>
-</resources>
diff --git a/packages/MtpDocumentsProvider/res/values-ml/strings.xml b/packages/MtpDocumentsProvider/res/values-ml/strings.xml
deleted file mode 100644
index 49eb847..0000000
--- a/packages/MtpDocumentsProvider/res/values-ml/strings.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<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="6271216747302322594">"MTP ഹോസ്റ്റ്"</string>
- <string name="downloads_app_label" msgid="7120690641874849726">"ഡൗണ്ലോഡുകൾ"</string>
- <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string>
- <string name="accessing_notification_title" msgid="3030133609230917944">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> ഉപകരണത്തിൽ നിന്ന് ഫയലുകൾ ആക്സസ്സ് ചെയ്യുന്നു"</string>
- <string name="error_busy_device" msgid="3997316850357386589">"രണ്ടാമത്തെ ഉപകരണം തിരക്കിലാണ്. അത് ലഭ്യമാകുന്നത് വരെ നിങ്ങൾക്ക് ഫയലുകൾ കൈമാറാൻ കഴിയില്ല."</string>
- <string name="error_locked_device" msgid="7557872102188356147">"ഫയലുകളൊന്നും കണ്ടെത്തിയില്ല. രണ്ടാമത്തെ ഉപകരണം ലോക്കുചെയ്ത നിലയിലായിരിക്കാം. ആണെങ്കിൽ, അൺലോക്കുചെയ്ത് വീണ്ടും ശ്രമിക്കുക."</string>
-</resources>
diff --git a/packages/MtpDocumentsProvider/res/values-mn/strings.xml b/packages/MtpDocumentsProvider/res/values-mn/strings.xml
deleted file mode 100644
index 43b8204..0000000
--- a/packages/MtpDocumentsProvider/res/values-mn/strings.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<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="6271216747302322594">"MTP Хост"</string>
- <string name="downloads_app_label" msgid="7120690641874849726">"Таталт"</string>
- <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string>
- <string name="accessing_notification_title" msgid="3030133609230917944">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g>-с файлд хандаж байна"</string>
- <string name="error_busy_device" msgid="3997316850357386589">"Нөгөө төхөөрөмж завгүй байна. Үүнийг боломжтой болох хүртэл файл шилжүүлэх боломжгүй."</string>
- <string name="error_locked_device" msgid="7557872102188356147">"Файл олдсонгүй. Нөгөө төхөөрөмж түгжигдсэн байж болзошгүй. Ингэсэн тохиолдолд түгжээг нь тайлаад, дахин оролдоно уу."</string>
-</resources>
diff --git a/packages/MtpDocumentsProvider/res/values-mr/strings.xml b/packages/MtpDocumentsProvider/res/values-mr/strings.xml
deleted file mode 100644
index 983112c..0000000
--- a/packages/MtpDocumentsProvider/res/values-mr/strings.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<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="6271216747302322594">"MTP होस्ट"</string>
- <string name="downloads_app_label" msgid="7120690641874849726">"डाउनलोड"</string>
- <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string>
- <string name="accessing_notification_title" msgid="3030133609230917944">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> मधून फायलींंमध्ये प्रवेश करत आहे"</string>
- <string name="error_busy_device" msgid="3997316850357386589">"दुसरे डिव्हाइस व्यस्त आहे. ते उपलब्ध होईपर्यंत तुम्ही फायली ट्रान्सफर करू शकत नाही."</string>
- <string name="error_locked_device" msgid="7557872102188356147">"कोणत्याही फायली आढळल्या नाहीत. दुसरे डिव्हाइस कदाचित बंद असू शकते. तसे असल्यास, ते अनलॉक करा आणि पुन्हा प्रयत्न करा."</string>
-</resources>
diff --git a/packages/MtpDocumentsProvider/res/values-ms/strings.xml b/packages/MtpDocumentsProvider/res/values-ms/strings.xml
deleted file mode 100644
index febec1d..0000000
--- a/packages/MtpDocumentsProvider/res/values-ms/strings.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<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="6271216747302322594">"Hos MTP"</string>
- <string name="downloads_app_label" msgid="7120690641874849726">"Muat turun"</string>
- <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string>
- <string name="accessing_notification_title" msgid="3030133609230917944">"Mengakses fail daripada <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string>
- <string name="error_busy_device" msgid="3997316850357386589">"Peranti lain sedang sibuk. Anda tidak boleh memindahkan fail sehingga peranti itu tersedia."</string>
- <string name="error_locked_device" msgid="7557872102188356147">"Tiada fail ditemui. Peranti lain itu mungkin dikunci. Jika benar, sila buka kuncinya dan cuba lagi."</string>
-</resources>
diff --git a/packages/MtpDocumentsProvider/res/values-my/strings.xml b/packages/MtpDocumentsProvider/res/values-my/strings.xml
deleted file mode 100644
index 8b509fb..0000000
--- a/packages/MtpDocumentsProvider/res/values-my/strings.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<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="6271216747302322594">"MTP လက်ခံစက်"</string>
- <string name="downloads_app_label" msgid="7120690641874849726">"ဒေါင်းလုဒ်များ"</string>
- <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string>
- <string name="accessing_notification_title" msgid="3030133609230917944">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> မှ ဖိုင်များကို အသုံးပြုနေသည်"</string>
- <string name="error_busy_device" msgid="3997316850357386589">"တခြားစက်ပစ္စည်းသည် မအားသေးပါ။ ၎င်းအဆင်သင့် မဖြစ်သေးသ၍ ဖိုင်များကို လွှဲပြောင်း၍ရမည် မဟုတ်ပါ။"</string>
- <string name="error_locked_device" msgid="7557872102188356147">"မည်သည့်ဖိုင်မျှ မတွေ့ပါ။ ၎င်းစက်ပစ္စည်းကို လော့ခ်ချထားပုံရပါသည်။ သို့ဖြစ်လျှင် ၎င်းကိုလော့ခ်ဖြုတ်ပြီး ထပ်လုပ်ကြည့်ပါ။"</string>
-</resources>
diff --git a/packages/MtpDocumentsProvider/res/values-nb/strings.xml b/packages/MtpDocumentsProvider/res/values-nb/strings.xml
deleted file mode 100644
index 40fabed..0000000
--- a/packages/MtpDocumentsProvider/res/values-nb/strings.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<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="6271216747302322594">"MTP-vert"</string>
- <string name="downloads_app_label" msgid="7120690641874849726">"Nedlastinger"</string>
- <string name="root_name" msgid="5819495383921089536">"<xliff:g id="STORAGE_NAME">%2$s</xliff:g> på <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string>
- <string name="accessing_notification_title" msgid="3030133609230917944">"Bruker filer på <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string>
- <string name="error_busy_device" msgid="3997316850357386589">"Den andre enheten er opptatt. Du kan ikke overføre filer før den er tilgjengelig."</string>
- <string name="error_locked_device" msgid="7557872102188356147">"Ingen filer ble funnet. Den andre enheten kan være låst. I så fall må du låse den opp og prøve igjen."</string>
-</resources>
diff --git a/packages/MtpDocumentsProvider/res/values-ne/strings.xml b/packages/MtpDocumentsProvider/res/values-ne/strings.xml
deleted file mode 100644
index 53c0954..0000000
--- a/packages/MtpDocumentsProvider/res/values-ne/strings.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<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="6271216747302322594">"MTP होस्ट"</string>
- <string name="downloads_app_label" msgid="7120690641874849726">"डाउनलोडहरू"</string>
- <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string>
- <string name="accessing_notification_title" msgid="3030133609230917944">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> बाट फाइलहरूमाथि पहुँच राख्दै"</string>
- <string name="error_busy_device" msgid="3997316850357386589">"अर्को यन्त्र व्यस्त छ। त्यो यन्त्र उपलब्ध नभएसम्म तपाईं फाइल स्थानान्तरण गर्न सक्नुहुन्न।"</string>
- <string name="error_locked_device" msgid="7557872102188356147">"कुनै फाइल भेट्टिएन। अर्को यन्त्र लक गरिएको हुन सक्छ। यदि त्यसो हो भने त्यसलाई अनलक गरेर फेरि प्रयास गर्नुहोस्।"</string>
-</resources>
diff --git a/packages/MtpDocumentsProvider/res/values-nl/strings.xml b/packages/MtpDocumentsProvider/res/values-nl/strings.xml
deleted file mode 100644
index b1a01b2..0000000
--- a/packages/MtpDocumentsProvider/res/values-nl/strings.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<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="6271216747302322594">"MTP-host"</string>
- <string name="downloads_app_label" msgid="7120690641874849726">"Downloads"</string>
- <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string>
- <string name="accessing_notification_title" msgid="3030133609230917944">"Bestanden openen op <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string>
- <string name="error_busy_device" msgid="3997316850357386589">"Het andere apparaat wordt gebruikt. Je moet wachten tot het beschikbaar is om bestanden te kunnen overzetten."</string>
- <string name="error_locked_device" msgid="7557872102188356147">"Geen bestanden gevonden. Het kan zijn dat het andere apparaat is vergrendeld. Als dat het geval is, ontgrendel je het en probeer je het opnieuw."</string>
-</resources>
diff --git a/packages/MtpDocumentsProvider/res/values-or/strings.xml b/packages/MtpDocumentsProvider/res/values-or/strings.xml
deleted file mode 100644
index 79de689..0000000
--- a/packages/MtpDocumentsProvider/res/values-or/strings.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<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="6271216747302322594">"MTP ହୋଷ୍ଟ"</string>
- <string name="downloads_app_label" msgid="7120690641874849726">"ଡାଉନଲୋଡ୍"</string>
- <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string>
- <string name="accessing_notification_title" msgid="3030133609230917944">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g>ରୁ ଫାଇଲ୍ ଆକ୍ସେସ୍ କରାଯାଉଛି"</string>
- <string name="error_busy_device" msgid="3997316850357386589">"ଅନ୍ୟ ଡିଭାଇସଟି ବ୍ୟସ୍ତ ଅଛି। ଏହା ଉପଲବ୍ଧ ନହେବା ପର୍ଯ୍ୟନ୍ତ ଆପଣ ଫାଇଲ୍ ଟ୍ରାନ୍ସଫର୍ କରିପାରିବେ ନାହିଁ।"</string>
- <string name="error_locked_device" msgid="7557872102188356147">"କୌଣସି ଫାଇଲ୍ ମିଳିଲା ନାହିଁ। ଅନ୍ୟ ଡିଭାଇସଟି ଲକ୍ ହୋଇଯାଇଥାଇପାରେ। ଯଦି ଏପରି ହୋଇଥାଏ, ଏହାକୁ ଅନଲକ୍ କରି ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
-</resources>
diff --git a/packages/MtpDocumentsProvider/res/values-pa/strings.xml b/packages/MtpDocumentsProvider/res/values-pa/strings.xml
deleted file mode 100644
index 7e3b892..0000000
--- a/packages/MtpDocumentsProvider/res/values-pa/strings.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<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="6271216747302322594">"MTP ਹੋਸਟ"</string>
- <string name="downloads_app_label" msgid="7120690641874849726">"ਡਾਊਨਲੋਡ"</string>
- <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string>
- <string name="accessing_notification_title" msgid="3030133609230917944">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> ਦੀਆਂ ਫ਼ਾਈਲਾਂ \'ਤੇ ਪਹੁੰਚ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ"</string>
- <string name="error_busy_device" msgid="3997316850357386589">"ਦੂਜਾ ਡੀਵਾਈਸ ਰੁਝੇਵੇਂ ਵਿੱਚ ਹੈ। ਉਸਦੇ ਉਪਲਬਧ ਹੋਣ ਤੱਕ ਤੁਸੀਂ ਫ਼ਾਈਲਾਂ ਦਾ ਤਬਾਦਲਾ ਨਹੀਂ ਕਰ ਸਕਦੇ।"</string>
- <string name="error_locked_device" msgid="7557872102188356147">"ਕੋਈ ਫ਼ਾਈਲਾਂ ਨਹੀਂ ਮਿਲੀਆਂ। ਹੋ ਸਕਦਾ ਹੈ ਕਿ ਦੂਜਾ ਡੀਵਾਈਸ ਲਾਕ ਹੋਵੇ। ਜੇਕਰ ਇੰਝ ਹੈ, ਤਾਂ ਉਸਨੂੰ ਅਣਲਾਕ ਕਰੋ ਅਤੇ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
-</resources>
diff --git a/packages/MtpDocumentsProvider/res/values-pl/strings.xml b/packages/MtpDocumentsProvider/res/values-pl/strings.xml
deleted file mode 100644
index 69fa0f4..0000000
--- a/packages/MtpDocumentsProvider/res/values-pl/strings.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<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="6271216747302322594">"Host MTP"</string>
- <string name="downloads_app_label" msgid="7120690641874849726">"Pobrane"</string>
- <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> – <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string>
- <string name="accessing_notification_title" msgid="3030133609230917944">"Uzyskuję dostęp do plików na urządzeniu <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string>
- <string name="error_busy_device" msgid="3997316850357386589">"Drugie urządzenie jest zajęte. Dopóki nie będzie dostępne, nie możesz przesłać plików."</string>
- <string name="error_locked_device" msgid="7557872102188356147">"Nie znaleziono plików. Drugie urządzenie może być zablokowane. Jeśli tak jest, odblokuj je i spróbuj ponownie."</string>
-</resources>
diff --git a/packages/MtpDocumentsProvider/res/values-pt-rBR/strings.xml b/packages/MtpDocumentsProvider/res/values-pt-rBR/strings.xml
deleted file mode 100644
index 03a1426..0000000
--- a/packages/MtpDocumentsProvider/res/values-pt-rBR/strings.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<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="6271216747302322594">"Host do MTP"</string>
- <string name="downloads_app_label" msgid="7120690641874849726">"Downloads"</string>
- <string name="root_name" msgid="5819495383921089536">"<xliff:g id="STORAGE_NAME">%2$s</xliff:g> do <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string>
- <string name="accessing_notification_title" msgid="3030133609230917944">"Acessando arquivos do <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string>
- <string name="error_busy_device" msgid="3997316850357386589">"O outro dispositivo está ocupado. Não é possível transferir arquivos até que ele esteja disponível."</string>
- <string name="error_locked_device" msgid="7557872102188356147">"Nenhum arquivo encontrado. É possível que o outro dispositivo esteja bloqueado. Se for o caso, desbloqueie-o e tente novamente."</string>
-</resources>
diff --git a/packages/MtpDocumentsProvider/res/values-pt-rPT/strings.xml b/packages/MtpDocumentsProvider/res/values-pt-rPT/strings.xml
deleted file mode 100644
index 05d32d4..0000000
--- a/packages/MtpDocumentsProvider/res/values-pt-rPT/strings.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<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="6271216747302322594">"Anfitrião MTP"</string>
- <string name="downloads_app_label" msgid="7120690641874849726">"Transferências"</string>
- <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string>
- <string name="accessing_notification_title" msgid="3030133609230917944">"Aceder a ficheiros do <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string>
- <string name="error_busy_device" msgid="3997316850357386589">"O outro dispositivo está ocupado. Não pode transferir os ficheiros enquanto não estiver disponível."</string>
- <string name="error_locked_device" msgid="7557872102188356147">"Nenhum ficheiro encontrado. O outro dispositivo pode estar bloqueado. Se assim for, desbloqueie e tente novamente."</string>
-</resources>
diff --git a/packages/MtpDocumentsProvider/res/values-pt/strings.xml b/packages/MtpDocumentsProvider/res/values-pt/strings.xml
deleted file mode 100644
index 03a1426..0000000
--- a/packages/MtpDocumentsProvider/res/values-pt/strings.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<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="6271216747302322594">"Host do MTP"</string>
- <string name="downloads_app_label" msgid="7120690641874849726">"Downloads"</string>
- <string name="root_name" msgid="5819495383921089536">"<xliff:g id="STORAGE_NAME">%2$s</xliff:g> do <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string>
- <string name="accessing_notification_title" msgid="3030133609230917944">"Acessando arquivos do <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string>
- <string name="error_busy_device" msgid="3997316850357386589">"O outro dispositivo está ocupado. Não é possível transferir arquivos até que ele esteja disponível."</string>
- <string name="error_locked_device" msgid="7557872102188356147">"Nenhum arquivo encontrado. É possível que o outro dispositivo esteja bloqueado. Se for o caso, desbloqueie-o e tente novamente."</string>
-</resources>
diff --git a/packages/MtpDocumentsProvider/res/values-ro/strings.xml b/packages/MtpDocumentsProvider/res/values-ro/strings.xml
deleted file mode 100644
index 21ebc57..0000000
--- a/packages/MtpDocumentsProvider/res/values-ro/strings.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<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="6271216747302322594">"Gazdă MTP"</string>
- <string name="downloads_app_label" msgid="7120690641874849726">"Descărcări"</string>
- <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string>
- <string name="accessing_notification_title" msgid="3030133609230917944">"Se accesează fișierele de pe <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string>
- <string name="error_busy_device" msgid="3997316850357386589">"Celălalt dispozitiv este ocupat. Nu puteți să transferați fișiere înainte să fie disponibil."</string>
- <string name="error_locked_device" msgid="7557872102188356147">"Nu s-au găsit fișiere. Este posibil ca celălalt dispozitiv să fie blocat. În acest caz, deblocați-l și încercați din nou."</string>
-</resources>
diff --git a/packages/MtpDocumentsProvider/res/values-ru/strings.xml b/packages/MtpDocumentsProvider/res/values-ru/strings.xml
deleted file mode 100644
index 717f12f..0000000
--- a/packages/MtpDocumentsProvider/res/values-ru/strings.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<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="6271216747302322594">"MTP-хост"</string>
- <string name="downloads_app_label" msgid="7120690641874849726">"Загрузки"</string>
- <string name="root_name" msgid="5819495383921089536">"<xliff:g id="STORAGE_NAME">%2$s</xliff:g> <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string>
- <string name="accessing_notification_title" msgid="3030133609230917944">"Доступ к файлам на устройстве <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>…"</string>
- <string name="error_busy_device" msgid="3997316850357386589">"Другое устройство занято. Вы сможете передать файлы, когда оно будет доступно."</string>
- <string name="error_locked_device" msgid="7557872102188356147">"Файлы не найдены. Если другое устройство заблокировано, разблокируйте его и повторите попытку."</string>
-</resources>
diff --git a/packages/MtpDocumentsProvider/res/values-si/strings.xml b/packages/MtpDocumentsProvider/res/values-si/strings.xml
deleted file mode 100644
index 7a096b0..0000000
--- a/packages/MtpDocumentsProvider/res/values-si/strings.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<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="6271216747302322594">"MTP සංග්රාහක"</string>
- <string name="downloads_app_label" msgid="7120690641874849726">"බාගැනීම්"</string>
- <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string>
- <string name="accessing_notification_title" msgid="3030133609230917944">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> වෙතින් ගොනු වෙත පිවිසීම"</string>
- <string name="error_busy_device" msgid="3997316850357386589">"අනෙක් උපාංගය කාර්ය බහුලය. එය ලබා ගත හැකි වන තෙක් ඔබට ගොනු මාරු කළ නොහැකිය."</string>
- <string name="error_locked_device" msgid="7557872102188356147">"ගොනු හමු නොවීය. අනෙක් උපාංගය අගුලු දමා තිබිය හැකිය. එසේ නම්, එය අගුලු හැර නැවත උත්සාහ කරන්න."</string>
-</resources>
diff --git a/packages/MtpDocumentsProvider/res/values-sk/strings.xml b/packages/MtpDocumentsProvider/res/values-sk/strings.xml
deleted file mode 100644
index 365e1b7..0000000
--- a/packages/MtpDocumentsProvider/res/values-sk/strings.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<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="6271216747302322594">"Hostiteľ MTP"</string>
- <string name="downloads_app_label" msgid="7120690641874849726">"Stiahnuté súbory"</string>
- <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string>
- <string name="accessing_notification_title" msgid="3030133609230917944">"Prístup k súborom zo zariadenia <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string>
- <string name="error_busy_device" msgid="3997316850357386589">"Druhé zariadenie je zaneprázdnené. Súbory bude možné preniesť, keď bude k dispozícii."</string>
- <string name="error_locked_device" msgid="7557872102188356147">"Nenašli sa žiadne súbory. Druhé zariadenie môže byť uzamknuté. Ak je to tak, odomknite ho a skúste to znova."</string>
-</resources>
diff --git a/packages/MtpDocumentsProvider/res/values-sl/strings.xml b/packages/MtpDocumentsProvider/res/values-sl/strings.xml
deleted file mode 100644
index 60945d6..0000000
--- a/packages/MtpDocumentsProvider/res/values-sl/strings.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<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="6271216747302322594">"Gostitelj MTP"</string>
- <string name="downloads_app_label" msgid="7120690641874849726">"Prenosi"</string>
- <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string>
- <string name="accessing_notification_title" msgid="3030133609230917944">"Dostopanje do datotek iz naprave <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string>
- <string name="error_busy_device" msgid="3997316850357386589">"Druga naprava ni na voljo. Dokler ne bo na voljo, ne bo mogoče prenašati datotek."</string>
- <string name="error_locked_device" msgid="7557872102188356147">"Ni datotek. Druga naprava je morda zaklenjena. Če je zaklenjena, jo odklenite in poskusite znova."</string>
-</resources>
diff --git a/packages/MtpDocumentsProvider/res/values-sq/strings.xml b/packages/MtpDocumentsProvider/res/values-sq/strings.xml
deleted file mode 100644
index d92f29f..0000000
--- a/packages/MtpDocumentsProvider/res/values-sq/strings.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<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="6271216747302322594">"Pritësi i protokollit MTP"</string>
- <string name="downloads_app_label" msgid="7120690641874849726">"Shkarkimet"</string>
- <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string>
- <string name="accessing_notification_title" msgid="3030133609230917944">"Po qaset te skedarët nga <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string>
- <string name="error_busy_device" msgid="3997316850357386589">"Pajisja tjetër është e zënë. Nuk mund të transferosh skedarë deri sa të jetë në dispozicion."</string>
- <string name="error_locked_device" msgid="7557872102188356147">"Nuk u gjet asnjë skedar. Pajisja tjetër mund të jetë e kyçur. Nëse po, shkyçe dhe provo përsëri."</string>
-</resources>
diff --git a/packages/MtpDocumentsProvider/res/values-sr/strings.xml b/packages/MtpDocumentsProvider/res/values-sr/strings.xml
deleted file mode 100644
index d91c5c4..0000000
--- a/packages/MtpDocumentsProvider/res/values-sr/strings.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<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="6271216747302322594">"MTP хост"</string>
- <string name="downloads_app_label" msgid="7120690641874849726">"Преузимања"</string>
- <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string>
- <string name="accessing_notification_title" msgid="3030133609230917944">"Приступ датотекама са уређаја <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string>
- <string name="error_busy_device" msgid="3997316850357386589">"Други уређај је заузет. Датотеке можете да пренесете тек кад он постане доступан."</string>
- <string name="error_locked_device" msgid="7557872102188356147">"Није пронађена ниједна датотека. Други уређај је можда закључан. Ако јесте, откључајте га и покушајте поново."</string>
-</resources>
diff --git a/packages/MtpDocumentsProvider/res/values-sv/strings.xml b/packages/MtpDocumentsProvider/res/values-sv/strings.xml
deleted file mode 100644
index 26818eb..0000000
--- a/packages/MtpDocumentsProvider/res/values-sv/strings.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<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="6271216747302322594">"MTP-värd"</string>
- <string name="downloads_app_label" msgid="7120690641874849726">"Nedladdningar"</string>
- <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string>
- <string name="accessing_notification_title" msgid="3030133609230917944">"Åtkomst till filer från <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string>
- <string name="error_busy_device" msgid="3997316850357386589">"Den andra enheten är upptagen. Du kan inte överföra filer förrän den är tillgänglig."</string>
- <string name="error_locked_device" msgid="7557872102188356147">"Inga filer hittades. Den andra enheten kan vara låst. Om den är det låser du upp den och försöker igen."</string>
-</resources>
diff --git a/packages/MtpDocumentsProvider/res/values-sw/strings.xml b/packages/MtpDocumentsProvider/res/values-sw/strings.xml
deleted file mode 100644
index de3ed54..0000000
--- a/packages/MtpDocumentsProvider/res/values-sw/strings.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<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="6271216747302322594">"Seva pangishi ya MTP"</string>
- <string name="downloads_app_label" msgid="7120690641874849726">"Vipakuliwa"</string>
- <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string>
- <string name="accessing_notification_title" msgid="3030133609230917944">"Inafikia faili kwenye <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string>
- <string name="error_busy_device" msgid="3997316850357386589">"Kifaa hicho kingine kinatumika. Huwezi kuhamisha faili hadi kipatikane."</string>
- <string name="error_locked_device" msgid="7557872102188356147">"Hakuna faili zilizopatikana. Huenda kifaa hicho kingine kimefungwa. Ikiwa kimefungwa, kifungue na ujaribu tena."</string>
-</resources>
diff --git a/packages/MtpDocumentsProvider/res/values-ta/strings.xml b/packages/MtpDocumentsProvider/res/values-ta/strings.xml
deleted file mode 100644
index c6e6e620..0000000
--- a/packages/MtpDocumentsProvider/res/values-ta/strings.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<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="6271216747302322594">"MTP ஹோஸ்ட்"</string>
- <string name="downloads_app_label" msgid="7120690641874849726">"இறக்கங்கள்"</string>
- <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string>
- <string name="accessing_notification_title" msgid="3030133609230917944">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> இலிருந்து கோப்புகளை அணுகுகிறது"</string>
- <string name="error_busy_device" msgid="3997316850357386589">"பிற சாதனம் பணிமிகுதியில் உள்ளதால், அந்தப் பணி முடியும் வரை கோப்புகளை இடமாற்ற முடியாது."</string>
- <string name="error_locked_device" msgid="7557872102188356147">"கோப்புகள் இல்லை. பிற சாதனம் பூட்டப்பட்டிருக்கக்கூடும் என்பதால் முதலில் அதைத் திறந்து, மீண்டும் முயலவும்."</string>
-</resources>
diff --git a/packages/MtpDocumentsProvider/res/values-te/strings.xml b/packages/MtpDocumentsProvider/res/values-te/strings.xml
deleted file mode 100644
index b3436bf..0000000
--- a/packages/MtpDocumentsProvider/res/values-te/strings.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<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="6271216747302322594">"MTP హోస్ట్"</string>
- <string name="downloads_app_label" msgid="7120690641874849726">"డౌన్లోడ్లు"</string>
- <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string>
- <string name="accessing_notification_title" msgid="3030133609230917944">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> నుండి ఫైల్లను యాక్సెస్ చేస్తోంది"</string>
- <string name="error_busy_device" msgid="3997316850357386589">"ఇతర పరికరం బిజీగా ఉంది. అది అందుబాటులోకి వచ్చే వరకు మీరు ఫైల్లను బదిలీ చేయలేరు."</string>
- <string name="error_locked_device" msgid="7557872102188356147">"ఫైల్లు ఏవీ కనుగొనబడలేదు. ఇతర పరికరం లాక్ చేయబడి ఉండవచ్చు. అలా జరిగి ఉంటే, దాన్ని అన్లాక్ చేసి, ఆపై మళ్లీ ప్రయత్నించండి."</string>
-</resources>
diff --git a/packages/MtpDocumentsProvider/res/values-th/strings.xml b/packages/MtpDocumentsProvider/res/values-th/strings.xml
deleted file mode 100644
index d2b62fe..0000000
--- a/packages/MtpDocumentsProvider/res/values-th/strings.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<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="6271216747302322594">"โฮสต์ MTP"</string>
- <string name="downloads_app_label" msgid="7120690641874849726">"ดาวน์โหลด"</string>
- <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string>
- <string name="accessing_notification_title" msgid="3030133609230917944">"กำลังเข้าถึงไฟล์จาก <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string>
- <string name="error_busy_device" msgid="3997316850357386589">"อุปกรณ์อีกเครื่องหนึ่งไม่ว่าง คุณไม่สามารถโอนไฟล์จนกว่าอุปกรณ์จะสามารถใช้ได้"</string>
- <string name="error_locked_device" msgid="7557872102188356147">"ไม่พบไฟล์ อุปกรณ์อีกเครื่องหนึ่งอาจล็อกอยู่ หากเป็นเช่นนั้น ให้ปลดล็อกและลองอีกครั้ง"</string>
-</resources>
diff --git a/packages/MtpDocumentsProvider/res/values-tl/strings.xml b/packages/MtpDocumentsProvider/res/values-tl/strings.xml
deleted file mode 100644
index 68b2eba..0000000
--- a/packages/MtpDocumentsProvider/res/values-tl/strings.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<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="6271216747302322594">"Host ng MTP"</string>
- <string name="downloads_app_label" msgid="7120690641874849726">"Mga Download"</string>
- <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string>
- <string name="accessing_notification_title" msgid="3030133609230917944">"Nag-a-access ng mga file mula sa <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string>
- <string name="error_busy_device" msgid="3997316850357386589">"Abala ang kabilang device. Hindi ka makakapaglipat ng mga file hanggang sa maging available ito."</string>
- <string name="error_locked_device" msgid="7557872102188356147">"Walang natagpuang mga file. Maaaring naka-lock ang kabilang device. Kung gayon, i-unlock ito at subukang muli."</string>
-</resources>
diff --git a/packages/MtpDocumentsProvider/res/values-tr/strings.xml b/packages/MtpDocumentsProvider/res/values-tr/strings.xml
deleted file mode 100644
index 14250ef..0000000
--- a/packages/MtpDocumentsProvider/res/values-tr/strings.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<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="6271216747302322594">"MTP Ana Makinesi"</string>
- <string name="downloads_app_label" msgid="7120690641874849726">"İndirilenler"</string>
- <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string>
- <string name="accessing_notification_title" msgid="3030133609230917944">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> cihazdaki dosyalara erişiliyor"</string>
- <string name="error_busy_device" msgid="3997316850357386589">"Diğer cihaz meşgul. Cihaz kullanılabilir duruma gelene kadar dosyaları aktaramazsınız."</string>
- <string name="error_locked_device" msgid="7557872102188356147">"Hiçbir dosya bulunamadı. Diğer cihaz kilitli olabilir. Kilitliyse, kilidini açıp tekrar deneyin."</string>
-</resources>
diff --git a/packages/MtpDocumentsProvider/res/values-uk/strings.xml b/packages/MtpDocumentsProvider/res/values-uk/strings.xml
deleted file mode 100644
index 8589f8c..0000000
--- a/packages/MtpDocumentsProvider/res/values-uk/strings.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<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="6271216747302322594">"Хост MTP"</string>
- <string name="downloads_app_label" msgid="7120690641874849726">"Завантаження"</string>
- <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string>
- <string name="accessing_notification_title" msgid="3030133609230917944">"Відкриваються файли з пристрою <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string>
- <string name="error_busy_device" msgid="3997316850357386589">"Інший пристрій зайнятий. Щоб передавати файли, він має бути доступним."</string>
- <string name="error_locked_device" msgid="7557872102188356147">"Не вдалося знайти файли. Можливо, інший пристрій заблоковано. У такому разі розблокуйте його та повторіть спробу."</string>
-</resources>
diff --git a/packages/MtpDocumentsProvider/res/values-ur/strings.xml b/packages/MtpDocumentsProvider/res/values-ur/strings.xml
deleted file mode 100644
index 17578ae..0000000
--- a/packages/MtpDocumentsProvider/res/values-ur/strings.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<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="6271216747302322594">"MTP میزبان"</string>
- <string name="downloads_app_label" msgid="7120690641874849726">"ڈاؤن لوڈز"</string>
- <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string>
- <string name="accessing_notification_title" msgid="3030133609230917944">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> سے فائلوں کی رسائی ہو رہی ہے"</string>
- <string name="error_busy_device" msgid="3997316850357386589">"دوسرا آلہ مصروف ہے۔ اس کے دستیاب ہونے تک آپ فائلیں منتقل نہیں کر سکتے۔"</string>
- <string name="error_locked_device" msgid="7557872102188356147">"کوئی فائلیں نہیں ملیں۔ ہو سکتا ہے دوسرا آلہ مقفل ہو۔ اگر ایسا ہے تو اسے غیر مقفل کریں اور دوبارہ کوشش کریں۔"</string>
-</resources>
diff --git a/packages/MtpDocumentsProvider/res/values-uz/strings.xml b/packages/MtpDocumentsProvider/res/values-uz/strings.xml
deleted file mode 100644
index c511172..0000000
--- a/packages/MtpDocumentsProvider/res/values-uz/strings.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<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="6271216747302322594">"MTP Host"</string>
- <string name="downloads_app_label" msgid="7120690641874849726">"Yuklanmalar"</string>
- <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g><xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string>
- <string name="accessing_notification_title" msgid="3030133609230917944">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> qurilmasidan fayllar o‘qilmoqda"</string>
- <string name="error_busy_device" msgid="3997316850357386589">"Ulangan qurilma band. U bo‘shamaguncha fayllarni o‘tkazib bo‘lmaydi."</string>
- <string name="error_locked_device" msgid="7557872102188356147">"Hech qanday fayl topilmadi. Ulangan qurilma qulflangan bo‘lishi mumkin. Agar shunday bo‘lsa, uni qulfdan chiqaring va qayta urinib ko‘ring."</string>
-</resources>
diff --git a/packages/MtpDocumentsProvider/res/values-vi/strings.xml b/packages/MtpDocumentsProvider/res/values-vi/strings.xml
deleted file mode 100644
index 0eb6310..0000000
--- a/packages/MtpDocumentsProvider/res/values-vi/strings.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<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="6271216747302322594">"Máy chủ MTP"</string>
- <string name="downloads_app_label" msgid="7120690641874849726">"Tải xuống"</string>
- <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string>
- <string name="accessing_notification_title" msgid="3030133609230917944">"Đang truy cập tệp từ <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string>
- <string name="error_busy_device" msgid="3997316850357386589">"Thiết bị khác đang bận. Bạn không thể chuyển tệp cho đến khi thiết bị rảnh."</string>
- <string name="error_locked_device" msgid="7557872102188356147">"Không tìm thấy tệp. Thiết bị khác có thể đã bị khóa. Nếu như vậy, hãy mở khóa thiết bị rồi thử lại."</string>
-</resources>
diff --git a/packages/MtpDocumentsProvider/res/values-zh-rCN/strings.xml b/packages/MtpDocumentsProvider/res/values-zh-rCN/strings.xml
deleted file mode 100644
index 7f1f394..0000000
--- a/packages/MtpDocumentsProvider/res/values-zh-rCN/strings.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<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="6271216747302322594">"MTP 主机"</string>
- <string name="downloads_app_label" msgid="7120690641874849726">"下载"</string>
- <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string>
- <string name="accessing_notification_title" msgid="3030133609230917944">"正在访问 <xliff:g id="DEVICE_MODEL">%1$s</xliff:g> 的文件"</string>
- <string name="error_busy_device" msgid="3997316850357386589">"另一台设备正忙。您必须等到该设备可用时才能传输文件。"</string>
- <string name="error_locked_device" msgid="7557872102188356147">"未找到任何文件。另一台设备可能处于锁定状态;如果是这样,请解锁该设备并重试。"</string>
-</resources>
diff --git a/packages/MtpDocumentsProvider/res/values-zh-rHK/strings.xml b/packages/MtpDocumentsProvider/res/values-zh-rHK/strings.xml
deleted file mode 100644
index be8c548..0000000
--- a/packages/MtpDocumentsProvider/res/values-zh-rHK/strings.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<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="6271216747302322594">"媒體傳輸協定主機"</string>
- <string name="downloads_app_label" msgid="7120690641874849726">"下載"</string>
- <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> 的「<xliff:g id="STORAGE_NAME">%2$s</xliff:g>」"</string>
- <string name="accessing_notification_title" msgid="3030133609230917944">"正在從 <xliff:g id="DEVICE_MODEL">%1$s</xliff:g> 存取檔案"</string>
- <string name="error_busy_device" msgid="3997316850357386589">"另一部裝置目前處於忙碌狀態,要等到該裝置可用時才能轉移檔案。"</string>
- <string name="error_locked_device" msgid="7557872102188356147">"找不到檔案。如果另一部裝置處於鎖定狀態,請解鎖該裝置,然後再試一次。"</string>
-</resources>
diff --git a/packages/MtpDocumentsProvider/res/values-zh-rTW/strings.xml b/packages/MtpDocumentsProvider/res/values-zh-rTW/strings.xml
deleted file mode 100644
index 2fe3c06..0000000
--- a/packages/MtpDocumentsProvider/res/values-zh-rTW/strings.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<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="6271216747302322594">"媒體傳輸通訊協定主機"</string>
- <string name="downloads_app_label" msgid="7120690641874849726">"下載"</string>
- <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string>
- <string name="accessing_notification_title" msgid="3030133609230917944">"正在從 <xliff:g id="DEVICE_MODEL">%1$s</xliff:g> 存取檔案"</string>
- <string name="error_busy_device" msgid="3997316850357386589">"另一個裝置忙碌中。必須等到該裝置可用時才能轉移檔案。"</string>
- <string name="error_locked_device" msgid="7557872102188356147">"找不到任何檔案。如果另一個裝置處於鎖定狀態,請將該裝置解鎖後再試一次。"</string>
-</resources>
diff --git a/packages/MtpDocumentsProvider/res/values-zu/strings.xml b/packages/MtpDocumentsProvider/res/values-zu/strings.xml
deleted file mode 100644
index f3f7206..0000000
--- a/packages/MtpDocumentsProvider/res/values-zu/strings.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<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="6271216747302322594">"Ukusingatha kwe-MTP"</string>
- <string name="downloads_app_label" msgid="7120690641874849726">"Okulandiwe"</string>
- <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string>
- <string name="accessing_notification_title" msgid="3030133609230917944">"Ifinyelela kumafayela kusukela ku-<xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string>
- <string name="error_busy_device" msgid="3997316850357386589">"Enye idivayisi imatasatasa. Awukwazi ukudlulisela amafayela ize itholakale."</string>
- <string name="error_locked_device" msgid="7557872102188356147">"Awekho amafayela atholiwe. Enye idivayisi kungenzeka ikhiyiwe. Uma kunjalo, yivule uphinde uzame futhi."</string>
-</resources>
diff --git a/packages/MtpDocumentsProvider/res/values/strings.xml b/packages/MtpDocumentsProvider/res/values/strings.xml
deleted file mode 100644
index b94aba0..0000000
--- a/packages/MtpDocumentsProvider/res/values/strings.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- App title of MtpDocumentsProvider [CHAR LIMIT=32] -->
- <string name="app_label">MTP Host</string>
- <!-- App title of DocumentsUI [CHAR LIMIT=32] -->
- <string name="downloads_app_label">Downloads</string>
- <!-- Name of MTP root shown in UI. Please align the two strings (device
- model and storage name) in proper order in the language.
- [CHAR LIMIT=32] -->
- <string name="root_name"><xliff:g id="device_model" example="Nexus 9">%1$s</xliff:g> <xliff:g id="storage_name" example="Internal Storage">%2$s</xliff:g></string>
- <!-- Title of notification showing Files app is accessing files in a MTP device. [CHAR LIMIT=60]-->
- <string name="accessing_notification_title">Accessing files from <xliff:g id="device_model" example="Nexus 9">%1$s</xliff:g></string>
- <!-- Error message shown in Files app when the connected MTP device is busy. [CHAR LIMIT=150]-->
- <string name="error_busy_device">The other device is busy. You can\'t transfer files until it\'s available.</string>
- <!-- Error message shown in Files app when the connected MTP device may be locked. [CHAR LIMIT=150]-->
- <string name="error_locked_device">No files found. The other device may be locked. If so, unlock it and try again.</string>
-</resources>
diff --git a/packages/MtpDocumentsProvider/res/xml/device_filter.xml b/packages/MtpDocumentsProvider/res/xml/device_filter.xml
deleted file mode 100644
index 7afa2b1..0000000
--- a/packages/MtpDocumentsProvider/res/xml/device_filter.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-<resources>
- <!-- filter for MTP/PTP devices -->
- <usb-device class="255" subclass="255" protocol="0" />
- <usb-device class="6" subclass="1" protocol="1" />
-</resources>
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/BusyDeviceException.java b/packages/MtpDocumentsProvider/src/com/android/mtp/BusyDeviceException.java
deleted file mode 100644
index 83488cd..0000000
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/BusyDeviceException.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (C) 2016 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.mtp;
-
-import java.io.IOException;
-
-/**
- * Exception thrown when the device is busy and the requested operation cannon be completed.
- */
-class BusyDeviceException extends IOException {
- BusyDeviceException() {
- super("The MTP device is busy.");
- }
-}
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/DocumentLoader.java b/packages/MtpDocumentsProvider/src/com/android/mtp/DocumentLoader.java
deleted file mode 100644
index 6ed4ea1..0000000
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/DocumentLoader.java
+++ /dev/null
@@ -1,432 +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.mtp;
-
-import android.annotation.Nullable;
-import android.annotation.WorkerThread;
-import android.content.ContentResolver;
-import android.database.Cursor;
-import android.mtp.MtpConstants;
-import android.mtp.MtpObjectInfo;
-import android.net.Uri;
-import android.os.Bundle;
-import android.os.Process;
-import android.provider.DocumentsContract;
-import android.util.Log;
-
-import com.android.internal.util.Preconditions;
-
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.LinkedList;
-
-/**
- * Loader for MTP document.
- * At the first request, the loader returns only first NUM_INITIAL_ENTRIES. Then it launches
- * background thread to load the rest documents and caches its result for next requests.
- * TODO: Rename this class to ObjectInfoLoader
- */
-class DocumentLoader implements AutoCloseable {
- static final int NUM_INITIAL_ENTRIES = 10;
- static final int NUM_LOADING_ENTRIES = 20;
- static final int NOTIFY_PERIOD_MS = 500;
-
- private final MtpDeviceRecord mDevice;
- private final MtpManager mMtpManager;
- private final ContentResolver mResolver;
- private final MtpDatabase mDatabase;
- private final TaskList mTaskList = new TaskList();
- private Thread mBackgroundThread;
-
- DocumentLoader(MtpDeviceRecord device, MtpManager mtpManager, ContentResolver resolver,
- MtpDatabase database) {
- mDevice = device;
- mMtpManager = mtpManager;
- mResolver = resolver;
- mDatabase = database;
- }
-
- /**
- * Queries the child documents of given parent.
- * It loads the first NUM_INITIAL_ENTRIES of object info, then launches the background thread
- * to load the rest.
- */
- synchronized Cursor queryChildDocuments(String[] columnNames, Identifier parent)
- throws IOException {
- assert parent.mDeviceId == mDevice.deviceId;
-
- LoaderTask task = mTaskList.findTask(parent);
- if (task == null) {
- if (parent.mDocumentId == null) {
- throw new FileNotFoundException("Parent not found.");
- }
- // TODO: Handle nit race around here.
- // 1. getObjectHandles.
- // 2. putNewDocument.
- // 3. startAddingChildDocuemnts.
- // 4. stopAddingChildDocuments - It removes the new document added at the step 2,
- // because it is not updated between start/stopAddingChildDocuments.
- task = new LoaderTask(mMtpManager, mDatabase, mDevice.operationsSupported, parent);
- task.loadObjectHandles();
- task.loadObjectInfoList(NUM_INITIAL_ENTRIES);
- } else {
- // Once remove the existing task in order to add it to the head of the list.
- mTaskList.remove(task);
- }
-
- mTaskList.addFirst(task);
- if (task.getState() == LoaderTask.STATE_LOADING) {
- resume();
- }
- return task.createCursor(mResolver, columnNames);
- }
-
- /**
- * Resumes a background thread.
- */
- synchronized void resume() {
- if (mBackgroundThread == null) {
- mBackgroundThread = new BackgroundLoaderThread();
- mBackgroundThread.start();
- }
- }
-
- /**
- * Obtains next task to be run in background thread, or release the reference to background
- * thread.
- *
- * Worker thread that receives null task needs to exit.
- */
- @WorkerThread
- synchronized @Nullable LoaderTask getNextTaskOrReleaseBackgroundThread() {
- Preconditions.checkState(mBackgroundThread != null);
-
- for (final LoaderTask task : mTaskList) {
- if (task.getState() == LoaderTask.STATE_LOADING) {
- return task;
- }
- }
-
- final Identifier identifier = mDatabase.getUnmappedDocumentsParent(mDevice.deviceId);
- if (identifier != null) {
- final LoaderTask existingTask = mTaskList.findTask(identifier);
- if (existingTask != null) {
- Preconditions.checkState(existingTask.getState() != LoaderTask.STATE_LOADING);
- mTaskList.remove(existingTask);
- }
- final LoaderTask newTask = new LoaderTask(
- mMtpManager, mDatabase, mDevice.operationsSupported, identifier);
- newTask.loadObjectHandles();
- mTaskList.addFirst(newTask);
- return newTask;
- }
-
- mBackgroundThread = null;
- return null;
- }
-
- /**
- * Terminates background thread.
- */
- @Override
- public void close() throws InterruptedException {
- final Thread thread;
- synchronized (this) {
- mTaskList.clear();
- thread = mBackgroundThread;
- }
- if (thread != null) {
- thread.interrupt();
- thread.join();
- }
- }
-
- synchronized void clearCompletedTasks() {
- mTaskList.clearCompletedTasks();
- }
-
- /**
- * Cancels the task for |parentIdentifier|.
- *
- * Task is removed from the cached list and it will create new task when |parentIdentifier|'s
- * children are queried next.
- */
- void cancelTask(Identifier parentIdentifier) {
- final LoaderTask task;
- synchronized (this) {
- task = mTaskList.findTask(parentIdentifier);
- }
- if (task != null) {
- task.cancel();
- mTaskList.remove(task);
- }
- }
-
- /**
- * Background thread to fetch object info.
- */
- private class BackgroundLoaderThread extends Thread {
- /**
- * Finds task that needs to be processed, then loads NUM_LOADING_ENTRIES of object info and
- * store them to the database. If it does not find a task, exits the thread.
- */
- @Override
- public void run() {
- Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
- while (!Thread.interrupted()) {
- final LoaderTask task = getNextTaskOrReleaseBackgroundThread();
- if (task == null) {
- return;
- }
- task.loadObjectInfoList(NUM_LOADING_ENTRIES);
- final boolean shouldNotify =
- task.getState() != LoaderTask.STATE_CANCELLED &&
- (task.mLastNotified.getTime() <
- new Date().getTime() - NOTIFY_PERIOD_MS ||
- task.getState() != LoaderTask.STATE_LOADING);
- if (shouldNotify) {
- task.notify(mResolver);
- }
- }
- }
- }
-
- /**
- * Task list that has helper methods to search/clear tasks.
- */
- private static class TaskList extends LinkedList<LoaderTask> {
- LoaderTask findTask(Identifier parent) {
- for (int i = 0; i < size(); i++) {
- if (get(i).mIdentifier.equals(parent))
- return get(i);
- }
- return null;
- }
-
- void clearCompletedTasks() {
- int i = 0;
- while (i < size()) {
- if (get(i).getState() == LoaderTask.STATE_COMPLETED) {
- remove(i);
- } else {
- i++;
- }
- }
- }
- }
-
- /**
- * Loader task.
- * Each task is responsible for fetching child documents for the given parent document.
- */
- private static class LoaderTask {
- static final int STATE_START = 0;
- static final int STATE_LOADING = 1;
- static final int STATE_COMPLETED = 2;
- static final int STATE_ERROR = 3;
- static final int STATE_CANCELLED = 4;
-
- final MtpManager mManager;
- final MtpDatabase mDatabase;
- final int[] mOperationsSupported;
- final Identifier mIdentifier;
- int[] mObjectHandles;
- int mState;
- Date mLastNotified;
- int mPosition;
- IOException mError;
-
- LoaderTask(MtpManager manager, MtpDatabase database, int[] operationsSupported,
- Identifier identifier) {
- assert operationsSupported != null;
- assert identifier.mDocumentType != MtpDatabaseConstants.DOCUMENT_TYPE_DEVICE;
- mManager = manager;
- mDatabase = database;
- mOperationsSupported = operationsSupported;
- mIdentifier = identifier;
- mObjectHandles = null;
- mState = STATE_START;
- mPosition = 0;
- mLastNotified = new Date();
- }
-
- synchronized void loadObjectHandles() {
- assert mState == STATE_START;
- mPosition = 0;
- int parentHandle = mIdentifier.mObjectHandle;
- // Need to pass the special value MtpManager.OBJECT_HANDLE_ROOT_CHILDREN to
- // getObjectHandles if we would like to obtain children under the root.
- if (mIdentifier.mDocumentType == MtpDatabaseConstants.DOCUMENT_TYPE_STORAGE) {
- parentHandle = MtpManager.OBJECT_HANDLE_ROOT_CHILDREN;
- }
- try {
- mObjectHandles = mManager.getObjectHandles(
- mIdentifier.mDeviceId, mIdentifier.mStorageId, parentHandle);
- mState = STATE_LOADING;
- } catch (IOException error) {
- mError = error;
- mState = STATE_ERROR;
- }
- }
-
- /**
- * Returns a cursor that traverses the child document of the parent document handled by the
- * task.
- * The returned task may have a EXTRA_LOADING flag.
- */
- synchronized Cursor createCursor(ContentResolver resolver, String[] columnNames)
- throws IOException {
- final Bundle extras = new Bundle();
- switch (getState()) {
- case STATE_LOADING:
- extras.putBoolean(DocumentsContract.EXTRA_LOADING, true);
- break;
- case STATE_ERROR:
- throw mError;
- }
- final Cursor cursor =
- mDatabase.queryChildDocuments(columnNames, mIdentifier.mDocumentId);
- cursor.setExtras(extras);
- cursor.setNotificationUri(resolver, createUri());
- return cursor;
- }
-
- /**
- * Stores object information into database.
- */
- void loadObjectInfoList(int count) {
- synchronized (this) {
- if (mState != STATE_LOADING) {
- return;
- }
- if (mPosition == 0) {
- try{
- mDatabase.getMapper().startAddingDocuments(mIdentifier.mDocumentId);
- } catch (FileNotFoundException error) {
- mError = error;
- mState = STATE_ERROR;
- return;
- }
- }
- }
- final ArrayList<MtpObjectInfo> infoList = new ArrayList<>();
- for (int chunkEnd = mPosition + count;
- mPosition < mObjectHandles.length && mPosition < chunkEnd;
- mPosition++) {
- try {
- infoList.add(mManager.getObjectInfo(
- mIdentifier.mDeviceId, mObjectHandles[mPosition]));
- } catch (IOException error) {
- Log.e(MtpDocumentsProvider.TAG, "Failed to load object info", error);
- }
- }
- final long[] objectSizeList = new long[infoList.size()];
- for (int i = 0; i < infoList.size(); i++) {
- final MtpObjectInfo info = infoList.get(i);
- // Compressed size is 32-bit unsigned integer but getCompressedSize returns the
- // value in Java int (signed 32-bit integer). Use getCompressedSizeLong instead
- // to get the value in Java long.
- if (info.getCompressedSizeLong() != 0xffffffffl) {
- objectSizeList[i] = info.getCompressedSizeLong();
- continue;
- }
-
- if (!MtpDeviceRecord.isSupported(
- mOperationsSupported,
- MtpConstants.OPERATION_GET_OBJECT_PROP_DESC) ||
- !MtpDeviceRecord.isSupported(
- mOperationsSupported,
- MtpConstants.OPERATION_GET_OBJECT_PROP_VALUE)) {
- objectSizeList[i] = -1;
- continue;
- }
-
- // Object size is more than 4GB.
- try {
- objectSizeList[i] = mManager.getObjectSizeLong(
- mIdentifier.mDeviceId,
- info.getObjectHandle(),
- info.getFormat());
- } catch (IOException error) {
- Log.e(MtpDocumentsProvider.TAG, "Failed to get object size property.", error);
- objectSizeList[i] = -1;
- }
- }
- synchronized (this) {
- // Check if the task is cancelled or not.
- if (mState != STATE_LOADING) {
- return;
- }
- try {
- mDatabase.getMapper().putChildDocuments(
- mIdentifier.mDeviceId,
- mIdentifier.mDocumentId,
- mOperationsSupported,
- infoList.toArray(new MtpObjectInfo[infoList.size()]),
- objectSizeList);
- } catch (FileNotFoundException error) {
- // Looks like the parent document information is removed.
- // Adding documents has already cancelled in Mapper so we don't need to invoke
- // stopAddingDocuments.
- mError = error;
- mState = STATE_ERROR;
- return;
- }
- if (mPosition >= mObjectHandles.length) {
- try{
- mDatabase.getMapper().stopAddingDocuments(mIdentifier.mDocumentId);
- mState = STATE_COMPLETED;
- } catch (FileNotFoundException error) {
- mError = error;
- mState = STATE_ERROR;
- return;
- }
- }
- }
- }
-
- /**
- * Cancels the task.
- */
- synchronized void cancel() {
- mDatabase.getMapper().cancelAddingDocuments(mIdentifier.mDocumentId);
- mState = STATE_CANCELLED;
- }
-
- /**
- * Returns a state of the task.
- */
- int getState() {
- return mState;
- }
-
- /**
- * Notifies a change of child list of the document.
- */
- void notify(ContentResolver resolver) {
- resolver.notifyChange(createUri(), null, false);
- mLastNotified = new Date();
- }
-
- private Uri createUri() {
- return DocumentsContract.buildChildDocumentsUri(
- MtpDocumentsProvider.AUTHORITY, mIdentifier.mDocumentId);
- }
- }
-}
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/Identifier.java b/packages/MtpDocumentsProvider/src/com/android/mtp/Identifier.java
deleted file mode 100644
index 124d207..0000000
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/Identifier.java
+++ /dev/null
@@ -1,81 +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.mtp;
-
-import java.util.Objects;
-import static com.android.mtp.MtpDatabaseConstants.DocumentType;
-
-/**
- * Static utilities for ID.
- */
-class Identifier {
- final int mDeviceId;
- final int mStorageId;
- final int mObjectHandle;
- final String mDocumentId;
- final @DocumentType int mDocumentType;
-
- Identifier(int deviceId, int storageId, int objectHandle, String documentId,
- @DocumentType int documentType) {
- mDeviceId = deviceId;
- mStorageId = storageId;
- mObjectHandle = objectHandle;
- mDocumentId = documentId;
- mDocumentType = documentType;
- }
-
- @Override
- public boolean equals(Object obj) {
- if (!(obj instanceof Identifier))
- return false;
- final Identifier other = (Identifier) obj;
- return mDeviceId == other.mDeviceId && mStorageId == other.mStorageId &&
- mObjectHandle == other.mObjectHandle && mDocumentId.equals(other.mDocumentId);
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(mDeviceId, mStorageId, mObjectHandle, mDocumentId);
- }
-
- @Override
- public String toString() {
- final StringBuilder builder = new StringBuilder();
- builder.append("Identifier { ");
-
- builder.append("mDeviceId: ");
- builder.append(mDeviceId);
- builder.append(", ");
-
- builder.append("mStorageId: ");
- builder.append(mStorageId);
- builder.append(", ");
-
- builder.append("mObjectHandle: ");
- builder.append(mObjectHandle);
- builder.append(", ");
-
- builder.append("mDocumentId: ");
- builder.append(mDocumentId);
- builder.append(", ");
-
- builder.append("mDocumentType: ");
- builder.append(mDocumentType);
- builder.append(" }");
- return builder.toString();
- }
-}
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/Mapper.java b/packages/MtpDocumentsProvider/src/com/android/mtp/Mapper.java
deleted file mode 100644
index 63f18f3..0000000
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/Mapper.java
+++ /dev/null
@@ -1,472 +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.mtp;
-
-import android.annotation.Nullable;
-import android.content.ContentValues;
-import android.database.Cursor;
-import android.database.DatabaseUtils;
-import android.database.sqlite.SQLiteDatabase;
-import android.mtp.MtpObjectInfo;
-import android.provider.DocumentsContract.Document;
-import android.provider.DocumentsContract.Root;
-import android.util.ArraySet;
-import android.util.Log;
-
-import com.android.internal.util.Preconditions;
-
-import java.io.FileNotFoundException;
-import java.util.Set;
-
-import static com.android.mtp.MtpDatabaseConstants.*;
-import static com.android.mtp.MtpDatabase.strings;
-
-/**
- * Mapping operations for MtpDatabase.
- * Also see the comments of {@link MtpDatabase}.
- */
-class Mapper {
- private static final String[] EMPTY_ARGS = new String[0];
- private final MtpDatabase mDatabase;
-
- /**
- * IDs which currently Mapper operates mapping for.
- */
- private final Set<String> mInMappingIds = new ArraySet<>();
-
- Mapper(MtpDatabase database) {
- mDatabase = database;
- }
-
- /**
- * Puts device information to database.
- *
- * @return If device is added to the database.
- * @throws FileNotFoundException
- */
- synchronized boolean putDeviceDocument(MtpDeviceRecord device) throws FileNotFoundException {
- final SQLiteDatabase database = mDatabase.getSQLiteDatabase();
- database.beginTransaction();
- try {
- final ContentValues[] valuesList = new ContentValues[1];
- final ContentValues[] extraValuesList = new ContentValues[1];
- valuesList[0] = new ContentValues();
- extraValuesList[0] = new ContentValues();
- MtpDatabase.getDeviceDocumentValues(valuesList[0], extraValuesList[0], device);
- final boolean changed = putDocuments(
- null,
- valuesList,
- extraValuesList,
- COLUMN_PARENT_DOCUMENT_ID + " IS NULL",
- EMPTY_ARGS,
- strings(COLUMN_DEVICE_ID, COLUMN_MAPPING_KEY));
- database.setTransactionSuccessful();
- return changed;
- } finally {
- database.endTransaction();
- }
- }
-
- /**
- * Puts root information to database.
- *
- * @param parentDocumentId Document ID of device document.
- * @param roots List of root information.
- * @return If roots are added or removed from the database.
- * @throws FileNotFoundException
- */
- synchronized boolean putStorageDocuments(
- String parentDocumentId, int[] operationsSupported, MtpRoot[] roots)
- throws FileNotFoundException {
- final SQLiteDatabase database = mDatabase.getSQLiteDatabase();
- database.beginTransaction();
- try {
- final ContentValues[] valuesList = new ContentValues[roots.length];
- final ContentValues[] extraValuesList = new ContentValues[roots.length];
- for (int i = 0; i < roots.length; i++) {
- valuesList[i] = new ContentValues();
- extraValuesList[i] = new ContentValues();
- MtpDatabase.getStorageDocumentValues(
- valuesList[i],
- extraValuesList[i],
- parentDocumentId,
- operationsSupported,
- roots[i]);
- }
- final boolean changed = putDocuments(
- parentDocumentId,
- valuesList,
- extraValuesList,
- COLUMN_PARENT_DOCUMENT_ID + " = ?",
- strings(parentDocumentId),
- strings(COLUMN_STORAGE_ID, Document.COLUMN_DISPLAY_NAME));
-
- database.setTransactionSuccessful();
- return changed;
- } finally {
- database.endTransaction();
- }
- }
-
- /**
- * Puts document information to database.
- *
- * @param deviceId Device ID
- * @param parentId Parent document ID.
- * @param documents List of document information.
- * @param documentSizes 64-bit size of documents. MtpObjectInfo#getComporessedSize will be
- * ignored because it does not contain 4GB> object size. Can be -1 if the size is unknown.
- * @throws FileNotFoundException
- */
- synchronized void putChildDocuments(
- int deviceId, String parentId,
- int[] operationsSupported,
- MtpObjectInfo[] documents,
- long[] documentSizes)
- throws FileNotFoundException {
- assert documents.length == documentSizes.length;
- final ContentValues[] valuesList = new ContentValues[documents.length];
- for (int i = 0; i < documents.length; i++) {
- valuesList[i] = new ContentValues();
- MtpDatabase.getObjectDocumentValues(
- valuesList[i],
- deviceId,
- parentId,
- operationsSupported,
- documents[i],
- documentSizes[i]);
- }
- putDocuments(
- parentId,
- valuesList,
- null,
- COLUMN_PARENT_DOCUMENT_ID + " = ?",
- strings(parentId),
- strings(COLUMN_OBJECT_HANDLE, Document.COLUMN_DISPLAY_NAME));
- }
-
- void clearMapping() {
- final SQLiteDatabase database = mDatabase.getSQLiteDatabase();
- database.beginTransaction();
- try {
- mInMappingIds.clear();
- // Disconnect all device rows.
- try {
- startAddingDocuments(null);
- stopAddingDocuments(null);
- } catch (FileNotFoundException exception) {
- Log.e(MtpDocumentsProvider.TAG, "Unexpected FileNotFoundException.", exception);
- throw new RuntimeException(exception);
- }
- database.setTransactionSuccessful();
- } finally {
- database.endTransaction();
- }
- }
-
- /**
- * Starts adding new documents.
- * It changes the direct child documents of the given document from VALID to INVALIDATED.
- * Note that it keeps DISCONNECTED documents as they are.
- *
- * @param parentDocumentId Parent document ID or NULL for root documents.
- * @throws FileNotFoundException
- */
- void startAddingDocuments(@Nullable String parentDocumentId) throws FileNotFoundException {
- final String selection;
- final String[] args;
- if (parentDocumentId != null) {
- selection = COLUMN_PARENT_DOCUMENT_ID + " = ?";
- args = strings(parentDocumentId);
- } else {
- selection = COLUMN_PARENT_DOCUMENT_ID + " IS NULL";
- args = EMPTY_ARGS;
- }
-
- final SQLiteDatabase database = mDatabase.getSQLiteDatabase();
- database.beginTransaction();
- try {
- getParentOrHaltMapping(parentDocumentId);
- Preconditions.checkState(!mInMappingIds.contains(parentDocumentId));
-
- // Set all valid documents as invalidated.
- final ContentValues values = new ContentValues();
- values.put(COLUMN_ROW_STATE, ROW_STATE_INVALIDATED);
- database.update(
- TABLE_DOCUMENTS,
- values,
- selection + " AND " + COLUMN_ROW_STATE + " = ?",
- DatabaseUtils.appendSelectionArgs(args, strings(ROW_STATE_VALID)));
-
- database.setTransactionSuccessful();
- mInMappingIds.add(parentDocumentId);
- } finally {
- database.endTransaction();
- }
- }
-
- /**
- * Puts the documents into the database.
- * If the mapping mode is not heuristic, it just adds the rows to the database or updates the
- * existing rows with the new values. If the mapping mode is heuristic, it adds some new rows as
- * 'pending' state when that rows may be corresponding to existing 'invalidated' rows. Then
- * {@link #stopAddingDocuments(String)} turns the pending rows into 'valid'
- * rows. If the methods adds rows to database, it updates valueList with correct document ID.
- *
- * @param parentId Parent document ID.
- * @param valuesList Values for documents to be stored in the database.
- * @param rootExtraValuesList Values for root extra to be stored in the database.
- * @param selection SQL where closure to select rows that shares the same parent.
- * @param args Argument for selection SQL.
- * @return Whether the database content is changed.
- * @throws FileNotFoundException When parentId is not registered in the database.
- */
- private boolean putDocuments(
- String parentId,
- ContentValues[] valuesList,
- @Nullable ContentValues[] rootExtraValuesList,
- String selection,
- String[] args,
- String[] mappingKeys) throws FileNotFoundException {
- final SQLiteDatabase database = mDatabase.getSQLiteDatabase();
- boolean changed = false;
- database.beginTransaction();
- try {
- getParentOrHaltMapping(parentId);
- Preconditions.checkState(mInMappingIds.contains(parentId));
- final ContentValues oldRowSnapshot = new ContentValues();
- final ContentValues newRowSnapshot = new ContentValues();
- for (int i = 0; i < valuesList.length; i++) {
- final ContentValues values = valuesList[i];
- final ContentValues rootExtraValues;
- if (rootExtraValuesList != null) {
- rootExtraValues = rootExtraValuesList[i];
- } else {
- rootExtraValues = null;
- }
- try (final Cursor candidateCursor =
- queryCandidate(selection, args, mappingKeys, values)) {
- final long rowId;
- if (candidateCursor == null) {
- rowId = database.insert(TABLE_DOCUMENTS, null, values);
- changed = true;
- } else {
- candidateCursor.moveToNext();
- rowId = candidateCursor.getLong(0);
- if (!changed) {
- mDatabase.writeRowSnapshot(String.valueOf(rowId), oldRowSnapshot);
- }
- database.update(
- TABLE_DOCUMENTS,
- values,
- SELECTION_DOCUMENT_ID,
- strings(rowId));
- }
- // Document ID is a primary integer key of the table. So the returned row
- // IDs should be same with the document ID.
- values.put(Document.COLUMN_DOCUMENT_ID, rowId);
- if (rootExtraValues != null) {
- rootExtraValues.put(Root.COLUMN_ROOT_ID, rowId);
- database.replace(TABLE_ROOT_EXTRA, null, rootExtraValues);
- }
-
- if (!changed) {
- mDatabase.writeRowSnapshot(String.valueOf(rowId), newRowSnapshot);
- // Put row state as string because SQLite returns snapshot values as string.
- oldRowSnapshot.put(COLUMN_ROW_STATE, String.valueOf(ROW_STATE_VALID));
- if (!oldRowSnapshot.equals(newRowSnapshot)) {
- changed = true;
- }
- }
- }
- }
-
- database.setTransactionSuccessful();
- return changed;
- } finally {
- database.endTransaction();
- }
- }
-
- /**
- * Stops adding documents.
- * It handles 'invalidated' and 'disconnected' documents which we don't put corresponding
- * documents so far.
- * If the type adding document is 'device' or 'storage', the document may appear again
- * afterward. The method marks such documents as 'disconnected'. If the type of adding document
- * is 'object', it seems the documents are really removed from the remote MTP device. So the
- * method deletes the metadata from the database.
- *
- * @param parentId Parent document ID or null for root documents.
- * @return Whether the methods changes file metadata in database.
- * @throws FileNotFoundException
- */
- boolean stopAddingDocuments(@Nullable String parentId) throws FileNotFoundException {
- final String selection;
- final String[] args;
- if (parentId != null) {
- selection = COLUMN_PARENT_DOCUMENT_ID + " = ?";
- args = strings(parentId);
- } else {
- selection = COLUMN_PARENT_DOCUMENT_ID + " IS NULL";
- args = EMPTY_ARGS;
- }
-
- final SQLiteDatabase database = mDatabase.getSQLiteDatabase();
- database.beginTransaction();
- try {
- final Identifier parentIdentifier = getParentOrHaltMapping(parentId);
- Preconditions.checkState(mInMappingIds.contains(parentId));
- mInMappingIds.remove(parentId);
-
- boolean changed = false;
- // Delete/disconnect all invalidated/disconnected rows that cannot be mapped.
- // If parentIdentifier is null, added documents are devices.
- // if parentIdentifier is DOCUMENT_TYPE_DEVICE, added documents are storages.
- final boolean keepUnmatchedDocument =
- parentIdentifier == null ||
- parentIdentifier.mDocumentType == DOCUMENT_TYPE_DEVICE;
- if (keepUnmatchedDocument) {
- if (mDatabase.disconnectDocumentsRecursively(
- COLUMN_ROW_STATE + " = ? AND " + selection,
- DatabaseUtils.appendSelectionArgs(strings(ROW_STATE_INVALIDATED), args))) {
- changed = true;
- }
- } else {
- if (mDatabase.deleteDocumentsAndRootsRecursively(
- COLUMN_ROW_STATE + " IN (?, ?) AND " + selection,
- DatabaseUtils.appendSelectionArgs(
- strings(ROW_STATE_INVALIDATED, ROW_STATE_DISCONNECTED), args))) {
- changed = true;
- }
- }
-
- database.setTransactionSuccessful();
- return changed;
- } finally {
- database.endTransaction();
- }
- }
-
- /**
- * Cancels adding documents.
- * @param parentId
- */
- void cancelAddingDocuments(@Nullable String parentId) {
- final String selection;
- final String[] args;
- if (parentId != null) {
- selection = COLUMN_PARENT_DOCUMENT_ID + " = ?";
- args = strings(parentId);
- } else {
- selection = COLUMN_PARENT_DOCUMENT_ID + " IS NULL";
- args = EMPTY_ARGS;
- }
-
- final SQLiteDatabase database = mDatabase.getSQLiteDatabase();
- database.beginTransaction();
- try {
- if (!mInMappingIds.contains(parentId)) {
- return;
- }
- mInMappingIds.remove(parentId);
- final ContentValues values = new ContentValues();
- values.put(COLUMN_ROW_STATE, ROW_STATE_VALID);
- mDatabase.getSQLiteDatabase().update(
- TABLE_DOCUMENTS,
- values,
- selection + " AND " + COLUMN_ROW_STATE + " = ?",
- DatabaseUtils.appendSelectionArgs(args, strings(ROW_STATE_INVALIDATED)));
- database.setTransactionSuccessful();
- } finally {
- database.endTransaction();
- }
- }
-
- /**
- * Queries candidate for each mappingKey, and returns the first cursor that includes a
- * candidate.
- *
- * @param selection Pre-selection for candidate.
- * @param args Arguments for selection.
- * @param mappingKeys List of mapping key columns.
- * @param values Values of document that Mapper tries to map.
- * @return Cursor for mapping candidate or null when Mapper does not find any candidate.
- */
- private @Nullable Cursor queryCandidate(
- String selection, String[] args, String[] mappingKeys, ContentValues values) {
- for (final String mappingKey : mappingKeys) {
- final Cursor candidateCursor = queryCandidate(selection, args, mappingKey, values);
- if (candidateCursor.getCount() == 0) {
- candidateCursor.close();
- continue;
- }
- return candidateCursor;
- }
- return null;
- }
-
- /**
- * Looks for mapping candidate with given mappingKey.
- *
- * @param selection Pre-selection for candidate.
- * @param args Arguments for selection.
- * @param mappingKey Column name of mapping key.
- * @param values Values of document that Mapper tries to map.
- * @return Cursor for mapping candidate.
- */
- private Cursor queryCandidate(
- String selection, String[] args, String mappingKey, ContentValues values) {
- final SQLiteDatabase database = mDatabase.getSQLiteDatabase();
- return database.query(
- TABLE_DOCUMENTS,
- strings(Document.COLUMN_DOCUMENT_ID),
- selection + " AND " +
- COLUMN_ROW_STATE + " IN (?, ?) AND " +
- mappingKey + " = ?",
- DatabaseUtils.appendSelectionArgs(
- args,
- strings(ROW_STATE_INVALIDATED,
- ROW_STATE_DISCONNECTED,
- values.getAsString(mappingKey))),
- null,
- null,
- null,
- "1");
- }
-
- /**
- * Returns the parent identifier from parent document ID if the parent ID is found in the
- * database. Otherwise it halts mapping and throws FileNotFoundException.
- *
- * @param parentId Parent document ID
- * @return Parent identifier
- * @throws FileNotFoundException
- */
- private @Nullable Identifier getParentOrHaltMapping(
- @Nullable String parentId) throws FileNotFoundException {
- if (parentId == null) {
- return null;
- }
- try {
- return mDatabase.createIdentifier(parentId);
- } catch (FileNotFoundException error) {
- mInMappingIds.remove(parentId);
- throw error;
- }
- }
-}
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabase.java b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabase.java
deleted file mode 100644
index 59c205a..0000000
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabase.java
+++ /dev/null
@@ -1,921 +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.mtp;
-
-import static com.android.mtp.MtpDatabaseConstants.*;
-
-import android.annotation.Nullable;
-import android.content.ContentValues;
-import android.content.Context;
-import android.content.res.Resources;
-import android.database.Cursor;
-import android.database.DatabaseUtils;
-import android.database.MatrixCursor;
-import android.database.MatrixCursor.RowBuilder;
-import android.database.sqlite.SQLiteDatabase;
-import android.database.sqlite.SQLiteOpenHelper;
-import android.database.sqlite.SQLiteQueryBuilder;
-import android.media.MediaFile;
-import android.mtp.MtpConstants;
-import android.mtp.MtpObjectInfo;
-import android.net.Uri;
-import android.provider.DocumentsContract;
-import android.provider.MetadataReader;
-import android.provider.DocumentsContract.Document;
-import android.provider.DocumentsContract.Root;
-
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.Preconditions;
-
-import java.io.FileNotFoundException;
-import java.util.HashSet;
-import java.util.Objects;
-import java.util.Set;
-
-/**
- * Database for MTP objects.
- * The object handle which is identifier for object in MTP protocol is not stable over sessions.
- * When we resume the process, we need to remap our document ID with MTP's object handle.
- *
- * If the remote MTP device is backed by typical file system, the file name
- * is unique among files in a directory. However, MTP protocol itself does
- * not guarantee the uniqueness of name so we cannot use fullpath as ID.
- *
- * Instead of fullpath, we use artificial ID generated by MtpDatabase itself. The database object
- * remembers the map of document ID and object handle, and remaps new object handle with document ID
- * by comparing the directory structure and object name.
- *
- * To start putting documents into the database, the client needs to call
- * {@link Mapper#startAddingDocuments(String)} with the parent document ID. Also it
- * needs to call {@link Mapper#stopAddingDocuments(String)} after putting all child
- * documents to the database. (All explanations are same for root documents)
- *
- * database.getMapper().startAddingDocuments();
- * database.getMapper().putChildDocuments();
- * database.getMapper().stopAddingDocuments();
- *
- * To update the existing documents, the client code can repeat to call the three methods again.
- * The newly added rows update corresponding existing rows that have same MTP identifier like
- * objectHandle.
- *
- * The client can call putChildDocuments multiple times to add documents by chunk, but it needs to
- * put all documents under the parent before calling stopAddingChildDocuments. Otherwise missing
- * documents are regarded as deleted, and will be removed from the database.
- *
- * If the client calls clearMtpIdentifier(), it clears MTP identifier in the database. In this case,
- * the database tries to find corresponding rows by using document's name instead of MTP identifier
- * at the next update cycle.
- *
- * TODO: Improve performance by SQL optimization.
- */
-class MtpDatabase {
- private final SQLiteDatabase mDatabase;
- private final Mapper mMapper;
-
- SQLiteDatabase getSQLiteDatabase() {
- return mDatabase;
- }
-
- MtpDatabase(Context context, int flags) {
- final OpenHelper helper = new OpenHelper(context, flags);
- mDatabase = helper.getWritableDatabase();
- mMapper = new Mapper(this);
- }
-
- void close() {
- mDatabase.close();
- }
-
- /**
- * Returns operations for mapping.
- * @return Mapping operations.
- */
- Mapper getMapper() {
- return mMapper;
- }
-
- /**
- * Queries roots information.
- * @param columnNames Column names defined in {@link android.provider.DocumentsContract.Root}.
- * @return Database cursor.
- */
- Cursor queryRoots(Resources resources, String[] columnNames) {
- final String selection =
- COLUMN_ROW_STATE + " IN (?, ?) AND " + COLUMN_DOCUMENT_TYPE + " = ?";
- final Cursor deviceCursor = mDatabase.query(
- TABLE_DOCUMENTS,
- strings(COLUMN_DEVICE_ID),
- selection,
- strings(ROW_STATE_VALID, ROW_STATE_INVALIDATED, DOCUMENT_TYPE_DEVICE),
- COLUMN_DEVICE_ID,
- null,
- null,
- null);
-
- try {
- final SQLiteQueryBuilder builder = new SQLiteQueryBuilder();
- builder.setTables(JOIN_ROOTS);
- builder.setProjectionMap(COLUMN_MAP_ROOTS);
- final MatrixCursor result = new MatrixCursor(columnNames);
- final ContentValues values = new ContentValues();
-
- while (deviceCursor.moveToNext()) {
- final int deviceId = deviceCursor.getInt(0);
- final Cursor storageCursor = builder.query(
- mDatabase,
- columnNames,
- selection + " AND " + COLUMN_DEVICE_ID + " = ?",
- strings(ROW_STATE_VALID,
- ROW_STATE_INVALIDATED,
- DOCUMENT_TYPE_STORAGE,
- deviceId),
- null,
- null,
- null);
- try {
- values.clear();
- try (final Cursor deviceRoot = builder.query(
- mDatabase,
- columnNames,
- selection + " AND " + COLUMN_DEVICE_ID + " = ?",
- strings(ROW_STATE_VALID,
- ROW_STATE_INVALIDATED,
- DOCUMENT_TYPE_DEVICE,
- deviceId),
- null,
- null,
- null)) {
- deviceRoot.moveToNext();
- DatabaseUtils.cursorRowToContentValues(deviceRoot, values);
- }
-
- if (storageCursor.getCount() != 0) {
- long capacityBytes = 0;
- long availableBytes = 0;
- final int capacityIndex =
- storageCursor.getColumnIndex(Root.COLUMN_CAPACITY_BYTES);
- final int availableIndex =
- storageCursor.getColumnIndex(Root.COLUMN_AVAILABLE_BYTES);
- while (storageCursor.moveToNext()) {
- // If requested columnNames does not include COLUMN_XXX_BYTES, we
- // don't calculate corresponding values.
- if (capacityIndex != -1) {
- capacityBytes += storageCursor.getLong(capacityIndex);
- }
- if (availableIndex != -1) {
- availableBytes += storageCursor.getLong(availableIndex);
- }
- }
- values.put(Root.COLUMN_CAPACITY_BYTES, capacityBytes);
- values.put(Root.COLUMN_AVAILABLE_BYTES, availableBytes);
- } else {
- values.putNull(Root.COLUMN_CAPACITY_BYTES);
- values.putNull(Root.COLUMN_AVAILABLE_BYTES);
- }
- if (storageCursor.getCount() == 1 && values.containsKey(Root.COLUMN_TITLE)) {
- storageCursor.moveToFirst();
- // Add storage name to device name if we have only 1 storage.
- values.put(
- Root.COLUMN_TITLE,
- resources.getString(
- R.string.root_name,
- values.getAsString(Root.COLUMN_TITLE),
- storageCursor.getString(
- storageCursor.getColumnIndex(Root.COLUMN_TITLE))));
- }
- } finally {
- storageCursor.close();
- }
-
- putValuesToCursor(values, result);
- }
-
- return result;
- } finally {
- deviceCursor.close();
- }
- }
-
- /**
- * Queries root documents information.
- * @param columnNames Column names defined in
- * {@link android.provider.DocumentsContract.Document}.
- * @return Database cursor.
- */
- @VisibleForTesting
- Cursor queryRootDocuments(String[] columnNames) {
- return mDatabase.query(
- TABLE_DOCUMENTS,
- columnNames,
- COLUMN_ROW_STATE + " IN (?, ?) AND " + COLUMN_DOCUMENT_TYPE + " = ?",
- strings(ROW_STATE_VALID, ROW_STATE_INVALIDATED, DOCUMENT_TYPE_STORAGE),
- null,
- null,
- null);
- }
-
- /**
- * Queries documents information.
- * @param columnNames Column names defined in
- * {@link android.provider.DocumentsContract.Document}.
- * @return Database cursor.
- */
- Cursor queryChildDocuments(String[] columnNames, String parentDocumentId) {
- return mDatabase.query(
- TABLE_DOCUMENTS,
- columnNames,
- COLUMN_ROW_STATE + " IN (?, ?) AND " + COLUMN_PARENT_DOCUMENT_ID + " = ?",
- strings(ROW_STATE_VALID, ROW_STATE_INVALIDATED, parentDocumentId),
- null,
- null,
- null);
- }
-
- /**
- * Returns document IDs of storages under the given device document.
- *
- * @param documentId Document ID that points a device.
- * @return Storage document IDs.
- * @throws FileNotFoundException The given document ID is not registered in database.
- */
- String[] getStorageDocumentIds(String documentId)
- throws FileNotFoundException {
- Preconditions.checkArgument(createIdentifier(documentId).mDocumentType ==
- DOCUMENT_TYPE_DEVICE);
- // Check if the parent document is device that has single storage.
- try (final Cursor cursor = mDatabase.query(
- TABLE_DOCUMENTS,
- strings(Document.COLUMN_DOCUMENT_ID),
- COLUMN_ROW_STATE + " IN (?, ?) AND " +
- COLUMN_PARENT_DOCUMENT_ID + " = ? AND " +
- COLUMN_DOCUMENT_TYPE + " = ?",
- strings(ROW_STATE_VALID,
- ROW_STATE_INVALIDATED,
- documentId,
- DOCUMENT_TYPE_STORAGE),
- null,
- null,
- null)) {
- final String[] ids = new String[cursor.getCount()];
- for (int i = 0; cursor.moveToNext(); i++) {
- ids[i] = cursor.getString(0);
- }
- return ids;
- }
- }
-
- /**
- * Queries a single document.
- * @param documentId
- * @param projection
- * @return Database cursor.
- */
- Cursor queryDocument(String documentId, String[] projection) {
- return mDatabase.query(
- TABLE_DOCUMENTS,
- projection,
- SELECTION_DOCUMENT_ID,
- strings(documentId),
- null,
- null,
- null,
- "1");
- }
-
- @Nullable String getDocumentIdForDevice(int deviceId) {
- final Cursor cursor = mDatabase.query(
- TABLE_DOCUMENTS,
- strings(Document.COLUMN_DOCUMENT_ID),
- COLUMN_DOCUMENT_TYPE + " = ? AND " + COLUMN_DEVICE_ID + " = ?",
- strings(DOCUMENT_TYPE_DEVICE, deviceId),
- null,
- null,
- null,
- "1");
- try {
- if (cursor.moveToNext()) {
- return cursor.getString(0);
- } else {
- return null;
- }
- } finally {
- cursor.close();
- }
- }
-
- /**
- * Obtains parent identifier.
- * @param documentId
- * @return parent identifier.
- * @throws FileNotFoundException
- */
- Identifier getParentIdentifier(String documentId) throws FileNotFoundException {
- final Cursor cursor = mDatabase.query(
- TABLE_DOCUMENTS,
- strings(COLUMN_PARENT_DOCUMENT_ID),
- SELECTION_DOCUMENT_ID,
- strings(documentId),
- null,
- null,
- null,
- "1");
- try {
- if (cursor.moveToNext()) {
- return createIdentifier(cursor.getString(0));
- } else {
- throw new FileNotFoundException("Cannot find a row having ID = " + documentId);
- }
- } finally {
- cursor.close();
- }
- }
-
- String getDeviceDocumentId(int deviceId) throws FileNotFoundException {
- try (final Cursor cursor = mDatabase.query(
- TABLE_DOCUMENTS,
- strings(Document.COLUMN_DOCUMENT_ID),
- COLUMN_DEVICE_ID + " = ? AND " + COLUMN_DOCUMENT_TYPE + " = ? AND " +
- COLUMN_ROW_STATE + " != ?",
- strings(deviceId, DOCUMENT_TYPE_DEVICE, ROW_STATE_DISCONNECTED),
- null,
- null,
- null,
- "1")) {
- if (cursor.getCount() > 0) {
- cursor.moveToNext();
- return cursor.getString(0);
- } else {
- throw new FileNotFoundException("The device ID not found: " + deviceId);
- }
- }
- }
-
- /**
- * Adds new document under the parent.
- * The method does not affect invalidated and pending documents because we know the document is
- * newly added and never mapped with existing ones.
- * @param parentDocumentId
- * @param info
- * @param size Object size. info#getCompressedSize() will be ignored because it does not contain
- * object size more than 4GB.
- * @return Document ID of added document.
- */
- String putNewDocument(
- int deviceId, String parentDocumentId, int[] operationsSupported, MtpObjectInfo info,
- long size) {
- final ContentValues values = new ContentValues();
- getObjectDocumentValues(
- values, deviceId, parentDocumentId, operationsSupported, info, size);
- mDatabase.beginTransaction();
- try {
- final long id = mDatabase.insert(TABLE_DOCUMENTS, null, values);
- mDatabase.setTransactionSuccessful();
- return Long.toString(id);
- } finally {
- mDatabase.endTransaction();
- }
- }
-
- /**
- * Deletes document and its children.
- * @param documentId
- */
- void deleteDocument(String documentId) {
- deleteDocumentsAndRootsRecursively(SELECTION_DOCUMENT_ID, strings(documentId));
- }
-
- /**
- * Gets identifier from document ID.
- * @param documentId Document ID.
- * @return Identifier.
- * @throws FileNotFoundException
- */
- Identifier createIdentifier(String documentId) throws FileNotFoundException {
- // Currently documentId is old format.
- final Cursor cursor = mDatabase.query(
- TABLE_DOCUMENTS,
- strings(COLUMN_DEVICE_ID,
- COLUMN_STORAGE_ID,
- COLUMN_OBJECT_HANDLE,
- COLUMN_DOCUMENT_TYPE),
- SELECTION_DOCUMENT_ID + " AND " + COLUMN_ROW_STATE + " IN (?, ?)",
- strings(documentId, ROW_STATE_VALID, ROW_STATE_INVALIDATED),
- null,
- null,
- null,
- "1");
- try {
- if (cursor.getCount() == 0) {
- throw new FileNotFoundException("ID \"" + documentId + "\" is not found.");
- } else {
- cursor.moveToNext();
- return new Identifier(
- cursor.getInt(0),
- cursor.getInt(1),
- cursor.getInt(2),
- documentId,
- cursor.getInt(3));
- }
- } finally {
- cursor.close();
- }
- }
-
- /**
- * Deletes a document, and its root information if the document is a root document.
- * @param selection Query to select documents.
- * @param args Arguments for selection.
- * @return Whether the method deletes rows.
- */
- boolean deleteDocumentsAndRootsRecursively(String selection, String[] args) {
- mDatabase.beginTransaction();
- try {
- boolean changed = false;
- final Cursor cursor = mDatabase.query(
- TABLE_DOCUMENTS,
- strings(Document.COLUMN_DOCUMENT_ID),
- selection,
- args,
- null,
- null,
- null);
- try {
- while (cursor.moveToNext()) {
- if (deleteDocumentsAndRootsRecursively(
- COLUMN_PARENT_DOCUMENT_ID + " = ?",
- strings(cursor.getString(0)))) {
- changed = true;
- }
- }
- } finally {
- cursor.close();
- }
- if (deleteDocumentsAndRoots(selection, args)) {
- changed = true;
- }
- mDatabase.setTransactionSuccessful();
- return changed;
- } finally {
- mDatabase.endTransaction();
- }
- }
-
- /**
- * Marks the documents and their child as disconnected documents.
- * @param selection
- * @param args
- * @return True if at least one row is updated.
- */
- boolean disconnectDocumentsRecursively(String selection, String[] args) {
- mDatabase.beginTransaction();
- try {
- boolean changed = false;
- try (final Cursor cursor = mDatabase.query(
- TABLE_DOCUMENTS,
- strings(Document.COLUMN_DOCUMENT_ID),
- selection,
- args,
- null,
- null,
- null)) {
- while (cursor.moveToNext()) {
- if (disconnectDocumentsRecursively(
- COLUMN_PARENT_DOCUMENT_ID + " = ?",
- strings(cursor.getString(0)))) {
- changed = true;
- }
- }
- }
- if (disconnectDocuments(selection, args)) {
- changed = true;
- }
- mDatabase.setTransactionSuccessful();
- return changed;
- } finally {
- mDatabase.endTransaction();
- }
- }
-
- boolean deleteDocumentsAndRoots(String selection, String[] args) {
- mDatabase.beginTransaction();
- try {
- int deleted = 0;
- deleted += mDatabase.delete(
- TABLE_ROOT_EXTRA,
- Root.COLUMN_ROOT_ID + " IN (" + SQLiteQueryBuilder.buildQueryString(
- false,
- TABLE_DOCUMENTS,
- new String[] { Document.COLUMN_DOCUMENT_ID },
- selection,
- null,
- null,
- null,
- null) + ")",
- args);
- deleted += mDatabase.delete(TABLE_DOCUMENTS, selection, args);
- mDatabase.setTransactionSuccessful();
- // TODO Remove mappingState.
- return deleted != 0;
- } finally {
- mDatabase.endTransaction();
- }
- }
-
- boolean disconnectDocuments(String selection, String[] args) {
- mDatabase.beginTransaction();
- try {
- final ContentValues values = new ContentValues();
- values.put(COLUMN_ROW_STATE, ROW_STATE_DISCONNECTED);
- values.putNull(COLUMN_DEVICE_ID);
- values.putNull(COLUMN_STORAGE_ID);
- values.putNull(COLUMN_OBJECT_HANDLE);
- final boolean updated = mDatabase.update(TABLE_DOCUMENTS, values, selection, args) != 0;
- mDatabase.setTransactionSuccessful();
- return updated;
- } finally {
- mDatabase.endTransaction();
- }
- }
-
- int getRowState(String documentId) throws FileNotFoundException {
- try (final Cursor cursor = mDatabase.query(
- TABLE_DOCUMENTS,
- strings(COLUMN_ROW_STATE),
- SELECTION_DOCUMENT_ID,
- strings(documentId),
- null,
- null,
- null)) {
- if (cursor.getCount() == 0) {
- throw new FileNotFoundException();
- }
- cursor.moveToNext();
- return cursor.getInt(0);
- }
- }
-
- void writeRowSnapshot(String documentId, ContentValues values) throws FileNotFoundException {
- try (final Cursor cursor = mDatabase.query(
- JOIN_ROOTS,
- strings("*"),
- SELECTION_DOCUMENT_ID,
- strings(documentId),
- null,
- null,
- null,
- "1")) {
- if (cursor.getCount() == 0) {
- throw new FileNotFoundException();
- }
- cursor.moveToNext();
- values.clear();
- DatabaseUtils.cursorRowToContentValues(cursor, values);
- }
- }
-
- void updateObject(String documentId, int deviceId, String parentId, int[] operationsSupported,
- MtpObjectInfo info, Long size) {
- final ContentValues values = new ContentValues();
- getObjectDocumentValues(values, deviceId, parentId, operationsSupported, info, size);
-
- mDatabase.beginTransaction();
- try {
- mDatabase.update(
- TABLE_DOCUMENTS,
- values,
- Document.COLUMN_DOCUMENT_ID + " = ?",
- strings(documentId));
- mDatabase.setTransactionSuccessful();
- } finally {
- mDatabase.endTransaction();
- }
- }
-
- /**
- * Obtains a document that has already mapped but has unmapped children.
- * @param deviceId Device to find documents.
- * @return Identifier of found document or null.
- */
- @Nullable Identifier getUnmappedDocumentsParent(int deviceId) {
- final String fromClosure =
- TABLE_DOCUMENTS + " AS child INNER JOIN " +
- TABLE_DOCUMENTS + " AS parent ON " +
- "child." + COLUMN_PARENT_DOCUMENT_ID + " = " +
- "parent." + Document.COLUMN_DOCUMENT_ID;
- final String whereClosure =
- "parent." + COLUMN_DEVICE_ID + " = ? AND " +
- "parent." + COLUMN_ROW_STATE + " IN (?, ?) AND " +
- "parent." + COLUMN_DOCUMENT_TYPE + " != ? AND " +
- "child." + COLUMN_ROW_STATE + " = ?";
- try (final Cursor cursor = mDatabase.query(
- fromClosure,
- strings("parent." + COLUMN_DEVICE_ID,
- "parent." + COLUMN_STORAGE_ID,
- "parent." + COLUMN_OBJECT_HANDLE,
- "parent." + Document.COLUMN_DOCUMENT_ID,
- "parent." + COLUMN_DOCUMENT_TYPE),
- whereClosure,
- strings(deviceId, ROW_STATE_VALID, ROW_STATE_INVALIDATED, DOCUMENT_TYPE_DEVICE,
- ROW_STATE_DISCONNECTED),
- null,
- null,
- null,
- "1")) {
- if (cursor.getCount() == 0) {
- return null;
- }
- cursor.moveToNext();
- return new Identifier(
- cursor.getInt(0),
- cursor.getInt(1),
- cursor.getInt(2),
- cursor.getString(3),
- cursor.getInt(4));
- }
- }
-
- /**
- * Removes metadata except for data used by outgoingPersistedUriPermissions.
- */
- void cleanDatabase(Uri[] outgoingPersistedUris) {
- mDatabase.beginTransaction();
- try {
- final Set<String> ids = new HashSet<>();
- for (final Uri uri : outgoingPersistedUris) {
- String documentId = DocumentsContract.getDocumentId(uri);
- while (documentId != null) {
- if (ids.contains(documentId)) {
- break;
- }
- ids.add(documentId);
- try (final Cursor cursor = mDatabase.query(
- TABLE_DOCUMENTS,
- strings(COLUMN_PARENT_DOCUMENT_ID),
- SELECTION_DOCUMENT_ID,
- strings(documentId),
- null,
- null,
- null)) {
- documentId = cursor.moveToNext() ? cursor.getString(0) : null;
- }
- }
- }
- deleteDocumentsAndRoots(
- Document.COLUMN_DOCUMENT_ID + " NOT IN " + getIdList(ids), null);
- mDatabase.setTransactionSuccessful();
- } finally {
- mDatabase.endTransaction();
- }
- }
-
- int getLastBootCount() {
- try (final Cursor cursor = mDatabase.query(
- TABLE_LAST_BOOT_COUNT, strings(COLUMN_VALUE), null, null, null, null, null)) {
- if (cursor.moveToNext()) {
- return cursor.getInt(0);
- } else {
- return 0;
- }
- }
- }
-
- void setLastBootCount(int value) {
- Preconditions.checkArgumentNonnegative(value, "Boot count must not be negative.");
- mDatabase.beginTransaction();
- try {
- final ContentValues values = new ContentValues();
- values.put(COLUMN_VALUE, value);
- mDatabase.delete(TABLE_LAST_BOOT_COUNT, null, null);
- mDatabase.insert(TABLE_LAST_BOOT_COUNT, null, values);
- mDatabase.setTransactionSuccessful();
- } finally {
- mDatabase.endTransaction();
- }
- }
-
- private static class OpenHelper extends SQLiteOpenHelper {
- public OpenHelper(Context context, int flags) {
- super(context,
- flags == FLAG_DATABASE_IN_MEMORY ? null : DATABASE_NAME,
- null,
- DATABASE_VERSION);
- }
-
- @Override
- public void onCreate(SQLiteDatabase db) {
- db.execSQL(QUERY_CREATE_DOCUMENTS);
- db.execSQL(QUERY_CREATE_ROOT_EXTRA);
- db.execSQL(QUERY_CREATE_LAST_BOOT_COUNT);
- }
-
- @Override
- public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
- db.execSQL("DROP TABLE IF EXISTS " + TABLE_DOCUMENTS);
- db.execSQL("DROP TABLE IF EXISTS " + TABLE_ROOT_EXTRA);
- db.execSQL("DROP TABLE IF EXISTS " + TABLE_LAST_BOOT_COUNT);
- onCreate(db);
- }
- }
-
- @VisibleForTesting
- static void deleteDatabase(Context context) {
- context.deleteDatabase(DATABASE_NAME);
- }
-
- static void getDeviceDocumentValues(
- ContentValues values,
- ContentValues extraValues,
- MtpDeviceRecord device) {
- values.clear();
- values.put(COLUMN_DEVICE_ID, device.deviceId);
- values.putNull(COLUMN_STORAGE_ID);
- values.putNull(COLUMN_OBJECT_HANDLE);
- values.putNull(COLUMN_PARENT_DOCUMENT_ID);
- values.put(COLUMN_ROW_STATE, ROW_STATE_VALID);
- values.put(COLUMN_DOCUMENT_TYPE, DOCUMENT_TYPE_DEVICE);
- values.put(COLUMN_MAPPING_KEY, device.deviceKey);
- values.put(Document.COLUMN_MIME_TYPE, Document.MIME_TYPE_DIR);
- values.put(Document.COLUMN_DISPLAY_NAME, device.name);
- values.putNull(Document.COLUMN_SUMMARY);
- values.putNull(Document.COLUMN_LAST_MODIFIED);
- values.put(Document.COLUMN_ICON, R.drawable.ic_root_mtp);
- values.put(Document.COLUMN_FLAGS, getDocumentFlags(
- device.operationsSupported,
- Document.MIME_TYPE_DIR,
- 0,
- MtpConstants.PROTECTION_STATUS_NONE,
- // Storages are placed under device so we cannot create a document just under
- // device.
- DOCUMENT_TYPE_DEVICE) & ~Document.FLAG_DIR_SUPPORTS_CREATE);
- values.putNull(Document.COLUMN_SIZE);
-
- extraValues.clear();
- extraValues.put(Root.COLUMN_FLAGS, getRootFlags(device.operationsSupported));
- extraValues.putNull(Root.COLUMN_AVAILABLE_BYTES);
- extraValues.putNull(Root.COLUMN_CAPACITY_BYTES);
- extraValues.put(Root.COLUMN_MIME_TYPES, "");
- }
-
- /**
- * Gets {@link ContentValues} for the given root.
- * @param values {@link ContentValues} that receives values.
- * @param extraValues {@link ContentValues} that receives extra values for roots.
- * @param parentDocumentId Parent document ID.
- * @param operationsSupported Array of Operation code supported by the device.
- * @param root Root to be converted {@link ContentValues}.
- */
- static void getStorageDocumentValues(
- ContentValues values,
- ContentValues extraValues,
- String parentDocumentId,
- int[] operationsSupported,
- MtpRoot root) {
- values.clear();
- values.put(COLUMN_DEVICE_ID, root.mDeviceId);
- values.put(COLUMN_STORAGE_ID, root.mStorageId);
- values.putNull(COLUMN_OBJECT_HANDLE);
- values.put(COLUMN_PARENT_DOCUMENT_ID, parentDocumentId);
- values.put(COLUMN_ROW_STATE, ROW_STATE_VALID);
- values.put(COLUMN_DOCUMENT_TYPE, DOCUMENT_TYPE_STORAGE);
- values.put(Document.COLUMN_MIME_TYPE, Document.MIME_TYPE_DIR);
- values.put(Document.COLUMN_DISPLAY_NAME, root.mDescription);
- values.putNull(Document.COLUMN_SUMMARY);
- values.putNull(Document.COLUMN_LAST_MODIFIED);
- values.put(Document.COLUMN_ICON, R.drawable.ic_root_mtp);
- values.put(Document.COLUMN_FLAGS, getDocumentFlags(
- operationsSupported,
- Document.MIME_TYPE_DIR,
- 0,
- MtpConstants.PROTECTION_STATUS_NONE,
- DOCUMENT_TYPE_STORAGE));
- values.put(Document.COLUMN_SIZE, root.mMaxCapacity - root.mFreeSpace);
-
- extraValues.put(Root.COLUMN_FLAGS, getRootFlags(operationsSupported));
- extraValues.put(Root.COLUMN_AVAILABLE_BYTES, root.mFreeSpace);
- extraValues.put(Root.COLUMN_CAPACITY_BYTES, root.mMaxCapacity);
- extraValues.put(Root.COLUMN_MIME_TYPES, "");
- }
-
- /**
- * Gets {@link ContentValues} for the given MTP object.
- * @param values {@link ContentValues} that receives values.
- * @param deviceId Device ID of the object.
- * @param parentId Parent document ID of the object.
- * @param info MTP object info. getCompressedSize will be ignored.
- * @param size 64-bit size of documents. Negative value is regarded as unknown size.
- */
- static void getObjectDocumentValues(
- ContentValues values, int deviceId, String parentId,
- int[] operationsSupported, MtpObjectInfo info, long size) {
- values.clear();
- final String mimeType = getMimeType(info);
- values.put(COLUMN_DEVICE_ID, deviceId);
- values.put(COLUMN_STORAGE_ID, info.getStorageId());
- values.put(COLUMN_OBJECT_HANDLE, info.getObjectHandle());
- values.put(COLUMN_PARENT_DOCUMENT_ID, parentId);
- values.put(COLUMN_ROW_STATE, ROW_STATE_VALID);
- values.put(COLUMN_DOCUMENT_TYPE, DOCUMENT_TYPE_OBJECT);
- values.put(Document.COLUMN_MIME_TYPE, mimeType);
- values.put(Document.COLUMN_DISPLAY_NAME, info.getName());
- values.putNull(Document.COLUMN_SUMMARY);
- values.put(
- Document.COLUMN_LAST_MODIFIED,
- info.getDateModified() != 0 ? info.getDateModified() : null);
- values.putNull(Document.COLUMN_ICON);
- values.put(Document.COLUMN_FLAGS, getDocumentFlags(
- operationsSupported, mimeType, info.getThumbCompressedSizeLong(),
- info.getProtectionStatus(), DOCUMENT_TYPE_OBJECT));
- if (size >= 0) {
- values.put(Document.COLUMN_SIZE, size);
- } else {
- values.putNull(Document.COLUMN_SIZE);
- }
- }
-
- private static String getMimeType(MtpObjectInfo info) {
- if (info.getFormat() == MtpConstants.FORMAT_ASSOCIATION) {
- return DocumentsContract.Document.MIME_TYPE_DIR;
- }
-
- return MediaFile.getMimeType(info.getName(), info.getFormat());
- }
-
- private static int getRootFlags(int[] operationsSupported) {
- int rootFlag = Root.FLAG_SUPPORTS_IS_CHILD | Root.FLAG_LOCAL_ONLY;
- if (MtpDeviceRecord.isWritingSupported(operationsSupported)) {
- rootFlag |= Root.FLAG_SUPPORTS_CREATE;
- }
- return rootFlag;
- }
-
- private static int getDocumentFlags(
- @Nullable int[] operationsSupported, String mimeType, long thumbnailSize,
- int protectionState, @DocumentType int documentType) {
- int flag = 0;
- if (!mimeType.equals(Document.MIME_TYPE_DIR) &&
- MtpDeviceRecord.isWritingSupported(operationsSupported) &&
- protectionState == MtpConstants.PROTECTION_STATUS_NONE) {
- flag |= Document.FLAG_SUPPORTS_WRITE;
- }
- if (MtpDeviceRecord.isSupported(
- operationsSupported, MtpConstants.OPERATION_DELETE_OBJECT) &&
- (protectionState == MtpConstants.PROTECTION_STATUS_NONE ||
- protectionState == MtpConstants.PROTECTION_STATUS_NON_TRANSFERABLE_DATA) &&
- documentType == DOCUMENT_TYPE_OBJECT) {
- flag |= Document.FLAG_SUPPORTS_DELETE;
- }
- if (mimeType.equals(Document.MIME_TYPE_DIR) &&
- MtpDeviceRecord.isWritingSupported(operationsSupported) &&
- protectionState == MtpConstants.PROTECTION_STATUS_NONE) {
- flag |= Document.FLAG_DIR_SUPPORTS_CREATE;
- }
- if (MetadataReader.isSupportedMimeType(mimeType)) {
- flag |= Document.FLAG_SUPPORTS_METADATA;
- }
- if (thumbnailSize > 0) {
- flag |= Document.FLAG_SUPPORTS_THUMBNAIL;
- }
- return flag;
- }
-
- static String[] strings(Object... args) {
- final String[] results = new String[args.length];
- for (int i = 0; i < args.length; i++) {
- results[i] = Objects.toString(args[i]);
- }
- return results;
- }
-
- static void putValuesToCursor(ContentValues values, MatrixCursor cursor) {
- final RowBuilder row = cursor.newRow();
- for (final String name : cursor.getColumnNames()) {
- row.add(values.get(name));
- }
- }
-
- private static String getIdList(Set<String> ids) {
- String result = "(";
- for (final String id : ids) {
- if (result.length() > 1) {
- result += ",";
- }
- result += id;
- }
- result += ")";
- return result;
- }
-}
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabaseConstants.java b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabaseConstants.java
deleted file mode 100644
index 6d98e34..0000000
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabaseConstants.java
+++ /dev/null
@@ -1,186 +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.mtp;
-
-import android.annotation.IntDef;
-import android.database.sqlite.SQLiteQueryBuilder;
-import android.provider.DocumentsContract.Document;
-import android.provider.DocumentsContract.Root;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * Class containing MtpDatabase constants.
- */
-class MtpDatabaseConstants {
- static final int DATABASE_VERSION = 5;
- static final String DATABASE_NAME = "database";
-
- static final int FLAG_DATABASE_IN_MEMORY = 1;
- static final int FLAG_DATABASE_IN_FILE = 0;
-
- /**
- * Table representing documents including root documents.
- */
- static final String TABLE_DOCUMENTS = "Documents";
-
- /**
- * Table containing additional information only available for root documents.
- * The table uses same primary keys with corresponding documents.
- */
- static final String TABLE_ROOT_EXTRA = "RootExtra";
-
- /**
- * Table containing last boot count.
- */
- static final String TABLE_LAST_BOOT_COUNT = "LastBootCount";
-
- /**
- * 'FROM' closure of joining TABLE_DOCUMENTS and TABLE_ROOT_EXTRA.
- */
- static final String JOIN_ROOTS = createJoinFromClosure(
- TABLE_DOCUMENTS,
- TABLE_ROOT_EXTRA,
- Document.COLUMN_DOCUMENT_ID,
- Root.COLUMN_ROOT_ID);
-
- static final String COLUMN_DEVICE_ID = "device_id";
- static final String COLUMN_STORAGE_ID = "storage_id";
- static final String COLUMN_OBJECT_HANDLE = "object_handle";
- static final String COLUMN_PARENT_DOCUMENT_ID = "parent_document_id";
- static final String COLUMN_DOCUMENT_TYPE = "document_type";
- static final String COLUMN_ROW_STATE = "row_state";
- static final String COLUMN_MAPPING_KEY = "mapping_key";
-
- /**
- * Value for TABLE_LAST_BOOT_COUNT.
- * Type: INTEGER
- */
- static final String COLUMN_VALUE = "value";
-
- /**
- * The state represents that the row has a valid object handle.
- */
- static final int ROW_STATE_VALID = 0;
-
- /**
- * The state represents that the rows added at the previous cycle and need to be updated with
- * fresh values.
- * The row may not have valid object handle. External application can still fetch the documents.
- * If the external application tries to fetch object handle, the provider resolves pending
- * documents with invalidated documents ahead.
- */
- static final int ROW_STATE_INVALIDATED = 1;
-
- /**
- * The documents are of device/storage that are disconnected now. The documents are invisible
- * but their document ID will be reuse when the device/storage is connected again.
- */
- static final int ROW_STATE_DISCONNECTED = 2;
-
- @IntDef(value = { DOCUMENT_TYPE_DEVICE, DOCUMENT_TYPE_STORAGE, DOCUMENT_TYPE_OBJECT })
- @Retention(RetentionPolicy.SOURCE)
- public @interface DocumentType {}
-
- /**
- * Document that represents a MTP device.
- */
- static final int DOCUMENT_TYPE_DEVICE = 0;
-
- /**
- * Document that represents a MTP storage.
- */
- static final int DOCUMENT_TYPE_STORAGE = 1;
-
- /**
- * Document that represents a MTP object.
- */
- static final int DOCUMENT_TYPE_OBJECT = 2;
-
- static final String SELECTION_DOCUMENT_ID = Document.COLUMN_DOCUMENT_ID + " = ?";
- static final String SELECTION_ROOT_ID = Root.COLUMN_ROOT_ID + " = ?";
-
- static final String QUERY_CREATE_DOCUMENTS =
- "CREATE TABLE " + TABLE_DOCUMENTS + " (" +
- Document.COLUMN_DOCUMENT_ID +
- " INTEGER PRIMARY KEY AUTOINCREMENT," +
- COLUMN_DEVICE_ID + " INTEGER," +
- COLUMN_STORAGE_ID + " INTEGER," +
- COLUMN_OBJECT_HANDLE + " INTEGER," +
- COLUMN_PARENT_DOCUMENT_ID + " INTEGER," +
- COLUMN_ROW_STATE + " INTEGER NOT NULL," +
- COLUMN_DOCUMENT_TYPE + " INTEGER NOT NULL," +
- COLUMN_MAPPING_KEY + " STRING," +
- Document.COLUMN_MIME_TYPE + " TEXT NOT NULL," +
- Document.COLUMN_DISPLAY_NAME + " TEXT NOT NULL," +
- Document.COLUMN_SUMMARY + " TEXT," +
- Document.COLUMN_LAST_MODIFIED + " INTEGER," +
- Document.COLUMN_ICON + " INTEGER," +
- Document.COLUMN_FLAGS + " INTEGER NOT NULL," +
- Document.COLUMN_SIZE + " INTEGER);";
-
- static final String QUERY_CREATE_ROOT_EXTRA =
- "CREATE TABLE " + TABLE_ROOT_EXTRA + " (" +
- Root.COLUMN_ROOT_ID + " INTEGER PRIMARY KEY," +
- Root.COLUMN_FLAGS + " INTEGER NOT NULL," +
- Root.COLUMN_AVAILABLE_BYTES + " INTEGER," +
- Root.COLUMN_CAPACITY_BYTES + " INTEGER," +
- Root.COLUMN_MIME_TYPES + " TEXT NOT NULL);";
-
- static final String QUERY_CREATE_LAST_BOOT_COUNT =
- "CREATE TABLE " + TABLE_LAST_BOOT_COUNT + " (value INTEGER NOT NULL);";
-
- /**
- * Map for columns names to provide DocumentContract.Root compatible columns.
- * @see SQLiteQueryBuilder#setProjectionMap(Map)
- */
- static final Map<String, String> COLUMN_MAP_ROOTS;
- static {
- COLUMN_MAP_ROOTS = new HashMap<>();
- COLUMN_MAP_ROOTS.put(Root.COLUMN_ROOT_ID, TABLE_ROOT_EXTRA + "." + Root.COLUMN_ROOT_ID);
- COLUMN_MAP_ROOTS.put(Root.COLUMN_FLAGS, TABLE_ROOT_EXTRA + "." + Root.COLUMN_FLAGS);
- COLUMN_MAP_ROOTS.put(
- Root.COLUMN_ICON,
- TABLE_DOCUMENTS + "." + Document.COLUMN_ICON + " AS " + Root.COLUMN_ICON);
- COLUMN_MAP_ROOTS.put(
- Root.COLUMN_TITLE,
- TABLE_DOCUMENTS + "." + Document.COLUMN_DISPLAY_NAME + " AS " + Root.COLUMN_TITLE);
- COLUMN_MAP_ROOTS.put(
- Root.COLUMN_SUMMARY,
- TABLE_DOCUMENTS + "." + Document.COLUMN_SUMMARY + " AS " + Root.COLUMN_SUMMARY);
- COLUMN_MAP_ROOTS.put(
- Root.COLUMN_DOCUMENT_ID,
- TABLE_DOCUMENTS + "." + Document.COLUMN_DOCUMENT_ID +
- " AS " + Root.COLUMN_DOCUMENT_ID);
- COLUMN_MAP_ROOTS.put(
- Root.COLUMN_AVAILABLE_BYTES, TABLE_ROOT_EXTRA + "." + Root.COLUMN_AVAILABLE_BYTES);
- COLUMN_MAP_ROOTS.put(
- Root.COLUMN_CAPACITY_BYTES, TABLE_ROOT_EXTRA + "." + Root.COLUMN_CAPACITY_BYTES);
- COLUMN_MAP_ROOTS.put(
- Root.COLUMN_MIME_TYPES, TABLE_ROOT_EXTRA + "." + Root.COLUMN_MIME_TYPES);
- COLUMN_MAP_ROOTS.put(COLUMN_DEVICE_ID, COLUMN_DEVICE_ID);
- }
-
- private static String createJoinFromClosure(
- String table1, String table2, String column1, String column2) {
- return table1 + " LEFT JOIN " + table2 +
- " ON " + table1 + "." + column1 + " = " + table2 + "." + column2;
- }
-}
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDeviceRecord.java b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDeviceRecord.java
deleted file mode 100644
index c52b81d..0000000
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDeviceRecord.java
+++ /dev/null
@@ -1,74 +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.mtp;
-
-import android.annotation.Nullable;
-import android.mtp.MtpConstants;
-
-class MtpDeviceRecord {
- public final int deviceId;
- public final String name;
- public final @Nullable String deviceKey;
- public final boolean opened;
- public final MtpRoot[] roots;
- public final @Nullable int[] operationsSupported;
- public final @Nullable int[] eventsSupported;
-
- MtpDeviceRecord(int deviceId, String name, @Nullable String deviceKey, boolean opened,
- MtpRoot[] roots, @Nullable int[] operationsSupported,
- @Nullable int[] eventsSupported) {
- this.deviceId = deviceId;
- this.name = name;
- this.opened = opened;
- this.roots = roots;
- this.deviceKey = deviceKey;
- this.operationsSupported = operationsSupported;
- this.eventsSupported = eventsSupported;
- }
-
- /**
- * Helper method to check operations/events are supported by the device or not.
- */
- static boolean isSupported(@Nullable int[] supportedList, int code) {
- if (supportedList == null) {
- return false;
- }
- for (int i = 0; i < supportedList.length; i++) {
- if (supportedList[i] == code) {
- return true;
- }
- }
- return false;
- }
-
- static boolean isPartialReadSupported(@Nullable int[] supportedList, long fileSize) {
- if (isSupported(supportedList, MtpConstants.OPERATION_GET_PARTIAL_OBJECT_64)) {
- return true;
- }
- if (0 <= fileSize &&
- fileSize <= 0xffffffffL &&
- isSupported(supportedList, MtpConstants.OPERATION_GET_PARTIAL_OBJECT)) {
- return true;
- }
- return false;
- }
-
- static boolean isWritingSupported(@Nullable int[] supportedList) {
- return isSupported(supportedList, MtpConstants.OPERATION_SEND_OBJECT_INFO) &&
- isSupported(supportedList, MtpConstants.OPERATION_SEND_OBJECT);
- }
-}
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java
deleted file mode 100644
index 8c8116b..0000000
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java
+++ /dev/null
@@ -1,856 +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.mtp;
-
-import android.annotation.Nullable;
-import android.content.ContentResolver;
-import android.content.ContentValues;
-import android.content.Context;
-import android.content.UriPermission;
-import android.content.res.AssetFileDescriptor;
-import android.content.res.Resources;
-import android.database.Cursor;
-import android.database.DatabaseUtils;
-import android.database.MatrixCursor;
-import android.database.sqlite.SQLiteDiskIOException;
-import android.graphics.Point;
-import android.media.MediaFile;
-import android.mtp.MtpConstants;
-import android.mtp.MtpObjectInfo;
-import android.net.Uri;
-import android.os.Bundle;
-import android.os.CancellationSignal;
-import android.os.FileUtils;
-import android.os.ParcelFileDescriptor;
-import android.os.ProxyFileDescriptorCallback;
-import android.os.storage.StorageManager;
-import android.provider.DocumentsContract;
-import android.provider.DocumentsContract.Document;
-import android.provider.DocumentsContract.Path;
-import android.provider.DocumentsContract.Root;
-import android.provider.DocumentsProvider;
-import android.provider.MetadataReader;
-import android.provider.Settings;
-import android.system.ErrnoException;
-import android.system.OsConstants;
-import android.util.Log;
-
-import com.android.internal.annotations.GuardedBy;
-import com.android.internal.annotations.VisibleForTesting;
-
-import libcore.io.IoUtils;
-
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.TimeoutException;
-
-/**
- * DocumentsProvider for MTP devices.
- */
-public class MtpDocumentsProvider extends DocumentsProvider {
- static final String AUTHORITY = "com.android.mtp.documents";
- static final String TAG = "MtpDocumentsProvider";
- static final String[] DEFAULT_ROOT_PROJECTION = new String[] {
- Root.COLUMN_ROOT_ID, Root.COLUMN_FLAGS, Root.COLUMN_ICON,
- Root.COLUMN_TITLE, Root.COLUMN_DOCUMENT_ID,
- Root.COLUMN_AVAILABLE_BYTES,
- };
- static final String[] DEFAULT_DOCUMENT_PROJECTION = new String[] {
- Document.COLUMN_DOCUMENT_ID, Document.COLUMN_MIME_TYPE,
- Document.COLUMN_DISPLAY_NAME, Document.COLUMN_LAST_MODIFIED,
- Document.COLUMN_FLAGS, Document.COLUMN_SIZE,
- };
-
- static final boolean DEBUG = false;
-
- private final Object mDeviceListLock = new Object();
-
- private static MtpDocumentsProvider sSingleton;
-
- private MtpManager mMtpManager;
- private ContentResolver mResolver;
- @GuardedBy("mDeviceListLock")
- private Map<Integer, DeviceToolkit> mDeviceToolkits;
- private RootScanner mRootScanner;
- private Resources mResources;
- private MtpDatabase mDatabase;
- private ServiceIntentSender mIntentSender;
- private Context mContext;
- private StorageManager mStorageManager;
-
- /**
- * Provides singleton instance to MtpDocumentsService.
- */
- static MtpDocumentsProvider getInstance() {
- return sSingleton;
- }
-
- @Override
- public boolean onCreate() {
- sSingleton = this;
- mContext = getContext();
- mResources = getContext().getResources();
- mMtpManager = new MtpManager(getContext());
- mResolver = getContext().getContentResolver();
- mDeviceToolkits = new HashMap<>();
- mDatabase = new MtpDatabase(getContext(), MtpDatabaseConstants.FLAG_DATABASE_IN_FILE);
- mRootScanner = new RootScanner(mResolver, mMtpManager, mDatabase);
- mIntentSender = new ServiceIntentSender(getContext());
- mStorageManager = getContext().getSystemService(StorageManager.class);
-
- // Check boot count and cleans database if it's first time to launch MtpDocumentsProvider
- // after booting.
- try {
- final int bootCount = Settings.Global.getInt(mResolver, Settings.Global.BOOT_COUNT, -1);
- final int lastBootCount = mDatabase.getLastBootCount();
- if (bootCount != -1 && bootCount != lastBootCount) {
- mDatabase.setLastBootCount(bootCount);
- final List<UriPermission> permissions =
- mResolver.getOutgoingPersistedUriPermissions();
- final Uri[] uris = new Uri[permissions.size()];
- for (int i = 0; i < permissions.size(); i++) {
- uris[i] = permissions.get(i).getUri();
- }
- mDatabase.cleanDatabase(uris);
- }
- } catch (SQLiteDiskIOException error) {
- // It can happen due to disk shortage.
- Log.e(TAG, "Failed to clean database.", error);
- return false;
- }
-
- resume();
- return true;
- }
-
- @VisibleForTesting
- boolean onCreateForTesting(
- Context context,
- Resources resources,
- MtpManager mtpManager,
- ContentResolver resolver,
- MtpDatabase database,
- StorageManager storageManager,
- ServiceIntentSender intentSender) {
- mContext = context;
- mResources = resources;
- mMtpManager = mtpManager;
- mResolver = resolver;
- mDeviceToolkits = new HashMap<>();
- mDatabase = database;
- mRootScanner = new RootScanner(mResolver, mMtpManager, mDatabase);
- mIntentSender = intentSender;
- mStorageManager = storageManager;
-
- resume();
- return true;
- }
-
- @Override
- public Cursor queryRoots(String[] projection) throws FileNotFoundException {
- if (projection == null) {
- projection = MtpDocumentsProvider.DEFAULT_ROOT_PROJECTION;
- }
- final Cursor cursor = mDatabase.queryRoots(mResources, projection);
- cursor.setNotificationUri(
- mResolver, DocumentsContract.buildRootsUri(MtpDocumentsProvider.AUTHORITY));
- return cursor;
- }
-
- @Override
- public Cursor queryDocument(String documentId, String[] projection)
- throws FileNotFoundException {
- if (projection == null) {
- projection = MtpDocumentsProvider.DEFAULT_DOCUMENT_PROJECTION;
- }
- final Cursor cursor = mDatabase.queryDocument(documentId, projection);
- final int cursorCount = cursor.getCount();
- if (cursorCount == 0) {
- cursor.close();
- throw new FileNotFoundException();
- } else if (cursorCount != 1) {
- cursor.close();
- Log.wtf(TAG, "Unexpected cursor size: " + cursorCount);
- return null;
- }
-
- final Identifier identifier = mDatabase.createIdentifier(documentId);
- if (identifier.mDocumentType != MtpDatabaseConstants.DOCUMENT_TYPE_DEVICE) {
- return cursor;
- }
- final String[] storageDocIds = mDatabase.getStorageDocumentIds(documentId);
- if (storageDocIds.length != 1) {
- return mDatabase.queryDocument(documentId, projection);
- }
-
- // If the documentId specifies a device having exact one storage, we repalce some device
- // attributes with the storage attributes.
- try {
- final String storageName;
- final int storageFlags;
- try (final Cursor storageCursor = mDatabase.queryDocument(
- storageDocIds[0],
- MtpDatabase.strings(Document.COLUMN_DISPLAY_NAME, Document.COLUMN_FLAGS))) {
- if (!storageCursor.moveToNext()) {
- throw new FileNotFoundException();
- }
- storageName = storageCursor.getString(0);
- storageFlags = storageCursor.getInt(1);
- }
-
- cursor.moveToNext();
- final ContentValues values = new ContentValues();
- DatabaseUtils.cursorRowToContentValues(cursor, values);
- if (values.containsKey(Document.COLUMN_DISPLAY_NAME)) {
- values.put(Document.COLUMN_DISPLAY_NAME, mResources.getString(
- R.string.root_name,
- values.getAsString(Document.COLUMN_DISPLAY_NAME),
- storageName));
- }
- values.put(Document.COLUMN_FLAGS, storageFlags);
- final MatrixCursor output = new MatrixCursor(projection, 1);
- MtpDatabase.putValuesToCursor(values, output);
- return output;
- } finally {
- cursor.close();
- }
- }
-
- @Override
- public Cursor queryChildDocuments(String parentDocumentId,
- String[] projection, String sortOrder) throws FileNotFoundException {
- if (DEBUG) {
- Log.d(TAG, "queryChildDocuments: " + parentDocumentId);
- }
- if (projection == null) {
- projection = MtpDocumentsProvider.DEFAULT_DOCUMENT_PROJECTION;
- }
- Identifier parentIdentifier = mDatabase.createIdentifier(parentDocumentId);
- try {
- openDevice(parentIdentifier.mDeviceId);
- if (parentIdentifier.mDocumentType == MtpDatabaseConstants.DOCUMENT_TYPE_DEVICE) {
- final String[] storageDocIds = mDatabase.getStorageDocumentIds(parentDocumentId);
- if (storageDocIds.length == 0) {
- // Remote device does not provide storages. Maybe it is locked.
- return createErrorCursor(projection, R.string.error_locked_device);
- } else if (storageDocIds.length > 1) {
- // Returns storage list from database.
- return mDatabase.queryChildDocuments(projection, parentDocumentId);
- }
-
- // Exact one storage is found. Skip storage and returns object in the single
- // storage.
- parentIdentifier = mDatabase.createIdentifier(storageDocIds[0]);
- }
-
- // Returns object list from document loader.
- return getDocumentLoader(parentIdentifier).queryChildDocuments(
- projection, parentIdentifier);
- } catch (BusyDeviceException exception) {
- return createErrorCursor(projection, R.string.error_busy_device);
- } catch (IOException exception) {
- Log.e(MtpDocumentsProvider.TAG, "queryChildDocuments", exception);
- throw new FileNotFoundException(exception.getMessage());
- }
- }
-
- @Override
- public ParcelFileDescriptor openDocument(
- String documentId, String mode, CancellationSignal signal)
- throws FileNotFoundException {
- if (DEBUG) {
- Log.d(TAG, "openDocument: " + documentId);
- }
- final Identifier identifier = mDatabase.createIdentifier(documentId);
- try {
- openDevice(identifier.mDeviceId);
- final MtpDeviceRecord device = getDeviceToolkit(identifier.mDeviceId).mDeviceRecord;
- // Turn off MODE_CREATE because openDocument does not allow to create new files.
- final int modeFlag =
- ParcelFileDescriptor.parseMode(mode) & ~ParcelFileDescriptor.MODE_CREATE;
- if ((modeFlag & ParcelFileDescriptor.MODE_READ_ONLY) != 0) {
- long fileSize;
- try {
- fileSize = getFileSize(documentId);
- } catch (UnsupportedOperationException exception) {
- fileSize = -1;
- }
- if (MtpDeviceRecord.isPartialReadSupported(
- device.operationsSupported, fileSize)) {
-
- return mStorageManager.openProxyFileDescriptor(
- modeFlag,
- new MtpProxyFileDescriptorCallback(Integer.parseInt(documentId)));
- } else {
- // If getPartialObject{|64} are not supported for the device, returns
- // non-seekable pipe FD instead.
- return getPipeManager(identifier).readDocument(mMtpManager, identifier);
- }
- } else if ((modeFlag & ParcelFileDescriptor.MODE_WRITE_ONLY) != 0) {
- // TODO: Clear the parent document loader task (if exists) and call notify
- // when writing is completed.
- if (MtpDeviceRecord.isWritingSupported(device.operationsSupported)) {
- return mStorageManager.openProxyFileDescriptor(
- modeFlag,
- new MtpProxyFileDescriptorCallback(Integer.parseInt(documentId)));
- } else {
- throw new UnsupportedOperationException(
- "The device does not support writing operation.");
- }
- } else {
- // TODO: Add support for "rw" mode.
- throw new UnsupportedOperationException("The provider does not support 'rw' mode.");
- }
- } catch (FileNotFoundException | RuntimeException error) {
- Log.e(MtpDocumentsProvider.TAG, "openDocument", error);
- throw error;
- } catch (IOException error) {
- Log.e(MtpDocumentsProvider.TAG, "openDocument", error);
- throw new IllegalStateException(error);
- }
- }
-
- @Override
- public AssetFileDescriptor openDocumentThumbnail(
- String documentId,
- Point sizeHint,
- CancellationSignal signal) throws FileNotFoundException {
- final Identifier identifier = mDatabase.createIdentifier(documentId);
- try {
- openDevice(identifier.mDeviceId);
- return new AssetFileDescriptor(
- getPipeManager(identifier).readThumbnail(mMtpManager, identifier),
- 0, // Start offset.
- AssetFileDescriptor.UNKNOWN_LENGTH);
- } catch (IOException error) {
- Log.e(MtpDocumentsProvider.TAG, "openDocumentThumbnail", error);
- throw new FileNotFoundException(error.getMessage());
- }
- }
-
- @Override
- public void deleteDocument(String documentId) throws FileNotFoundException {
- try {
- final Identifier identifier = mDatabase.createIdentifier(documentId);
- openDevice(identifier.mDeviceId);
- final Identifier parentIdentifier = mDatabase.getParentIdentifier(documentId);
- mMtpManager.deleteDocument(identifier.mDeviceId, identifier.mObjectHandle);
- mDatabase.deleteDocument(documentId);
- getDocumentLoader(parentIdentifier).cancelTask(parentIdentifier);
- notifyChildDocumentsChange(parentIdentifier.mDocumentId);
- if (parentIdentifier.mDocumentType == MtpDatabaseConstants.DOCUMENT_TYPE_STORAGE) {
- // If the parent is storage, the object might be appeared as child of device because
- // we skip storage when the device has only one storage.
- final Identifier deviceIdentifier = mDatabase.getParentIdentifier(
- parentIdentifier.mDocumentId);
- notifyChildDocumentsChange(deviceIdentifier.mDocumentId);
- }
- } catch (IOException error) {
- Log.e(MtpDocumentsProvider.TAG, "deleteDocument", error);
- throw new FileNotFoundException(error.getMessage());
- }
- }
-
- @Override
- public void onTrimMemory(int level) {
- synchronized (mDeviceListLock) {
- for (final DeviceToolkit toolkit : mDeviceToolkits.values()) {
- toolkit.mDocumentLoader.clearCompletedTasks();
- }
- }
- }
-
- @Override
- public String createDocument(String parentDocumentId, String mimeType, String displayName)
- throws FileNotFoundException {
- if (DEBUG) {
- Log.d(TAG, "createDocument: " + displayName);
- }
- final Identifier parentId;
- final MtpDeviceRecord record;
- final ParcelFileDescriptor[] pipe;
- try {
- parentId = mDatabase.createIdentifier(parentDocumentId);
- openDevice(parentId.mDeviceId);
- record = getDeviceToolkit(parentId.mDeviceId).mDeviceRecord;
- if (!MtpDeviceRecord.isWritingSupported(record.operationsSupported)) {
- throw new UnsupportedOperationException(
- "Writing operation is not supported by the device.");
- }
-
- final int parentObjectHandle;
- final int storageId;
- switch (parentId.mDocumentType) {
- case MtpDatabaseConstants.DOCUMENT_TYPE_DEVICE:
- final String[] storageDocumentIds =
- mDatabase.getStorageDocumentIds(parentId.mDocumentId);
- if (storageDocumentIds.length == 1) {
- final String newDocumentId =
- createDocument(storageDocumentIds[0], mimeType, displayName);
- notifyChildDocumentsChange(parentDocumentId);
- return newDocumentId;
- } else {
- throw new UnsupportedOperationException(
- "Cannot create a file under the device.");
- }
- case MtpDatabaseConstants.DOCUMENT_TYPE_STORAGE:
- storageId = parentId.mStorageId;
- parentObjectHandle = -1;
- break;
- case MtpDatabaseConstants.DOCUMENT_TYPE_OBJECT:
- storageId = parentId.mStorageId;
- parentObjectHandle = parentId.mObjectHandle;
- break;
- default:
- throw new IllegalArgumentException("Unexpected document type.");
- }
-
- pipe = ParcelFileDescriptor.createReliablePipe();
- int objectHandle = -1;
- MtpObjectInfo info = null;
- try {
- pipe[0].close(); // 0 bytes for a new document.
-
- final int formatCode = Document.MIME_TYPE_DIR.equals(mimeType) ?
- MtpConstants.FORMAT_ASSOCIATION :
- MediaFile.getFormatCode(displayName, mimeType);
- info = new MtpObjectInfo.Builder()
- .setStorageId(storageId)
- .setParent(parentObjectHandle)
- .setFormat(formatCode)
- .setName(displayName)
- .build();
-
- final String[] parts = FileUtils.splitFileName(mimeType, displayName);
- final String baseName = parts[0];
- final String extension = parts[1];
- for (int i = 0; i <= 32; i++) {
- final MtpObjectInfo infoUniqueName;
- if (i == 0) {
- infoUniqueName = info;
- } else {
- String suffixedName = baseName + " (" + i + " )";
- if (!extension.isEmpty()) {
- suffixedName += "." + extension;
- }
- infoUniqueName =
- new MtpObjectInfo.Builder(info).setName(suffixedName).build();
- }
- try {
- objectHandle = mMtpManager.createDocument(
- parentId.mDeviceId, infoUniqueName, pipe[1]);
- break;
- } catch (SendObjectInfoFailure exp) {
- // This can be caused when we have an existing file with the same name.
- continue;
- }
- }
- } finally {
- pipe[1].close();
- }
- if (objectHandle == -1) {
- throw new IllegalArgumentException(
- "The file name \"" + displayName + "\" is conflicted with existing files " +
- "and the provider failed to find unique name.");
- }
- final MtpObjectInfo infoWithHandle =
- new MtpObjectInfo.Builder(info).setObjectHandle(objectHandle).build();
- final String documentId = mDatabase.putNewDocument(
- parentId.mDeviceId, parentDocumentId, record.operationsSupported,
- infoWithHandle, 0l);
- getDocumentLoader(parentId).cancelTask(parentId);
- notifyChildDocumentsChange(parentDocumentId);
- return documentId;
- } catch (FileNotFoundException | RuntimeException error) {
- Log.e(TAG, "createDocument", error);
- throw error;
- } catch (IOException error) {
- Log.e(TAG, "createDocument", error);
- throw new IllegalStateException(error);
- }
- }
-
- @Override
- public Path findDocumentPath(String parentDocumentId, String childDocumentId)
- throws FileNotFoundException {
- final LinkedList<String> ids = new LinkedList<>();
- final Identifier childIdentifier = mDatabase.createIdentifier(childDocumentId);
-
- Identifier i = childIdentifier;
- outer: while (true) {
- if (i.mDocumentId.equals(parentDocumentId)) {
- ids.addFirst(i.mDocumentId);
- break;
- }
- switch (i.mDocumentType) {
- case MtpDatabaseConstants.DOCUMENT_TYPE_OBJECT:
- ids.addFirst(i.mDocumentId);
- i = mDatabase.getParentIdentifier(i.mDocumentId);
- break;
- case MtpDatabaseConstants.DOCUMENT_TYPE_STORAGE: {
- // Check if there is the multiple storage.
- final Identifier deviceIdentifier =
- mDatabase.getParentIdentifier(i.mDocumentId);
- final String[] storageIds =
- mDatabase.getStorageDocumentIds(deviceIdentifier.mDocumentId);
- // Add storage's document ID to the path only when the device has multiple
- // storages.
- if (storageIds.length > 1) {
- ids.addFirst(i.mDocumentId);
- break outer;
- }
- i = deviceIdentifier;
- break;
- }
- case MtpDatabaseConstants.DOCUMENT_TYPE_DEVICE:
- ids.addFirst(i.mDocumentId);
- break outer;
- }
- }
-
- if (parentDocumentId != null) {
- return new Path(null, ids);
- } else {
- return new Path(/* Should be same with root ID */ i.mDocumentId, ids);
- }
- }
-
- @Override
- public boolean isChildDocument(String parentDocumentId, String documentId) {
- try {
- Identifier identifier = mDatabase.createIdentifier(documentId);
- while (true) {
- if (parentDocumentId.equals(identifier.mDocumentId)) {
- return true;
- }
- if (identifier.mDocumentType == MtpDatabaseConstants.DOCUMENT_TYPE_DEVICE) {
- return false;
- }
- identifier = mDatabase.getParentIdentifier(identifier.mDocumentId);
- }
- } catch (FileNotFoundException error) {
- return false;
- }
- }
-
- @Override
- public @Nullable Bundle getDocumentMetadata(String docId) throws FileNotFoundException {
- String mimeType = getDocumentType(docId);
-
- if (!MetadataReader.isSupportedMimeType(mimeType)) {
- return null;
- }
-
- InputStream stream = null;
- try {
- stream = new ParcelFileDescriptor.AutoCloseInputStream(
- openDocument(docId, "r", null));
- Bundle metadata = new Bundle();
- MetadataReader.getMetadata(metadata, stream, mimeType, null);
- return metadata;
- } catch (IOException e) {
- Log.e(TAG, "An error occurred retrieving the metadata", e);
- return null;
- } finally {
- IoUtils.closeQuietly(stream);
- }
- }
-
- void openDevice(int deviceId) throws IOException {
- synchronized (mDeviceListLock) {
- if (mDeviceToolkits.containsKey(deviceId)) {
- return;
- }
- if (DEBUG) {
- Log.d(TAG, "Open device " + deviceId);
- }
- final MtpDeviceRecord device = mMtpManager.openDevice(deviceId);
- final DeviceToolkit toolkit =
- new DeviceToolkit(mMtpManager, mResolver, mDatabase, device);
- mDeviceToolkits.put(deviceId, toolkit);
- mIntentSender.sendUpdateNotificationIntent(getOpenedDeviceRecordsCache());
- try {
- mRootScanner.resume().await();
- } catch (InterruptedException error) {
- Log.e(TAG, "openDevice", error);
- }
- // Resume document loader to remap disconnected document ID. Must be invoked after the
- // root scanner resumes.
- toolkit.mDocumentLoader.resume();
- }
- }
-
- void closeDevice(int deviceId) throws IOException, InterruptedException {
- synchronized (mDeviceListLock) {
- closeDeviceInternal(deviceId);
- mIntentSender.sendUpdateNotificationIntent(getOpenedDeviceRecordsCache());
- }
- mRootScanner.resume();
- }
-
- MtpDeviceRecord[] getOpenedDeviceRecordsCache() {
- synchronized (mDeviceListLock) {
- final MtpDeviceRecord[] records = new MtpDeviceRecord[mDeviceToolkits.size()];
- int i = 0;
- for (final DeviceToolkit toolkit : mDeviceToolkits.values()) {
- records[i] = toolkit.mDeviceRecord;
- i++;
- }
- return records;
- }
- }
-
- /**
- * Obtains document ID for the given device ID.
- * @param deviceId
- * @return document ID
- * @throws FileNotFoundException device ID has not been build.
- */
- public String getDeviceDocumentId(int deviceId) throws FileNotFoundException {
- return mDatabase.getDeviceDocumentId(deviceId);
- }
-
- /**
- * Resumes root scanner to handle the update of device list.
- */
- void resumeRootScanner() {
- if (DEBUG) {
- Log.d(MtpDocumentsProvider.TAG, "resumeRootScanner");
- }
- mRootScanner.resume();
- }
-
- /**
- * Finalize the content provider for unit tests.
- */
- @Override
- public void shutdown() {
- synchronized (mDeviceListLock) {
- try {
- // Copy the opened key set because it will be modified when closing devices.
- final Integer[] keySet =
- mDeviceToolkits.keySet().toArray(new Integer[mDeviceToolkits.size()]);
- for (final int id : keySet) {
- closeDeviceInternal(id);
- }
- mRootScanner.pause();
- } catch (InterruptedException | IOException | TimeoutException e) {
- // It should fail unit tests by throwing runtime exception.
- throw new RuntimeException(e);
- } finally {
- mDatabase.close();
- super.shutdown();
- }
- }
- }
-
- private void notifyChildDocumentsChange(String parentDocumentId) {
- mResolver.notifyChange(
- DocumentsContract.buildChildDocumentsUri(AUTHORITY, parentDocumentId),
- null,
- false);
- }
-
- /**
- * Clears MTP identifier in the database.
- */
- private void resume() {
- synchronized (mDeviceListLock) {
- mDatabase.getMapper().clearMapping();
- }
- }
-
- private void closeDeviceInternal(int deviceId) throws IOException, InterruptedException {
- // TODO: Flush the device before closing (if not closed externally).
- if (!mDeviceToolkits.containsKey(deviceId)) {
- return;
- }
- if (DEBUG) {
- Log.d(TAG, "Close device " + deviceId);
- }
- getDeviceToolkit(deviceId).close();
- mDeviceToolkits.remove(deviceId);
- mMtpManager.closeDevice(deviceId);
- }
-
- private DeviceToolkit getDeviceToolkit(int deviceId) throws FileNotFoundException {
- synchronized (mDeviceListLock) {
- final DeviceToolkit toolkit = mDeviceToolkits.get(deviceId);
- if (toolkit == null) {
- throw new FileNotFoundException();
- }
- return toolkit;
- }
- }
-
- private PipeManager getPipeManager(Identifier identifier) throws FileNotFoundException {
- return getDeviceToolkit(identifier.mDeviceId).mPipeManager;
- }
-
- private DocumentLoader getDocumentLoader(Identifier identifier) throws FileNotFoundException {
- return getDeviceToolkit(identifier.mDeviceId).mDocumentLoader;
- }
-
- private long getFileSize(String documentId) throws FileNotFoundException {
- final Cursor cursor = mDatabase.queryDocument(
- documentId,
- MtpDatabase.strings(Document.COLUMN_SIZE, Document.COLUMN_DISPLAY_NAME));
- try {
- if (cursor.moveToNext()) {
- if (cursor.isNull(0)) {
- throw new UnsupportedOperationException();
- }
- return cursor.getLong(0);
- } else {
- throw new FileNotFoundException();
- }
- } finally {
- cursor.close();
- }
- }
-
- /**
- * Creates empty cursor with specific error message.
- *
- * @param projection Column names.
- * @param stringResId String resource ID of error message.
- * @return Empty cursor with error message.
- */
- private Cursor createErrorCursor(String[] projection, int stringResId) {
- final Bundle bundle = new Bundle();
- bundle.putString(DocumentsContract.EXTRA_ERROR, mResources.getString(stringResId));
- final Cursor cursor = new MatrixCursor(projection);
- cursor.setExtras(bundle);
- return cursor;
- }
-
- private static class DeviceToolkit implements AutoCloseable {
- public final PipeManager mPipeManager;
- public final DocumentLoader mDocumentLoader;
- public final MtpDeviceRecord mDeviceRecord;
-
- public DeviceToolkit(MtpManager manager,
- ContentResolver resolver,
- MtpDatabase database,
- MtpDeviceRecord record) {
- mPipeManager = new PipeManager(database);
- mDocumentLoader = new DocumentLoader(record, manager, resolver, database);
- mDeviceRecord = record;
- }
-
- @Override
- public void close() throws InterruptedException {
- mPipeManager.close();
- mDocumentLoader.close();
- }
- }
-
- private class MtpProxyFileDescriptorCallback extends ProxyFileDescriptorCallback {
- private final int mInode;
- private MtpFileWriter mWriter;
-
- MtpProxyFileDescriptorCallback(int inode) {
- mInode = inode;
- }
-
- @Override
- public long onGetSize() throws ErrnoException {
- try {
- return getFileSize(String.valueOf(mInode));
- } catch (FileNotFoundException e) {
- Log.e(TAG, e.getMessage(), e);
- throw new ErrnoException("onGetSize", OsConstants.ENOENT);
- }
- }
-
- @Override
- public int onRead(long offset, int size, byte[] data) throws ErrnoException {
- try {
- final Identifier identifier = mDatabase.createIdentifier(Integer.toString(mInode));
- final MtpDeviceRecord record = getDeviceToolkit(identifier.mDeviceId).mDeviceRecord;
- if (MtpDeviceRecord.isSupported(
- record.operationsSupported, MtpConstants.OPERATION_GET_PARTIAL_OBJECT_64)) {
-
- return (int) mMtpManager.getPartialObject64(
- identifier.mDeviceId, identifier.mObjectHandle, offset, size, data);
-
- }
- if (0 <= offset && offset <= 0xffffffffL && MtpDeviceRecord.isSupported(
- record.operationsSupported, MtpConstants.OPERATION_GET_PARTIAL_OBJECT)) {
- return (int) mMtpManager.getPartialObject(
- identifier.mDeviceId, identifier.mObjectHandle, offset, size, data);
- }
- throw new ErrnoException("onRead", OsConstants.ENOTSUP);
- } catch (IOException e) {
- Log.e(TAG, e.getMessage(), e);
- throw new ErrnoException("onRead", OsConstants.EIO);
- }
- }
-
- @Override
- public int onWrite(long offset, int size, byte[] data) throws ErrnoException {
- try {
- if (mWriter == null) {
- mWriter = new MtpFileWriter(mContext, String.valueOf(mInode));
- }
- return mWriter.write(offset, size, data);
- } catch (IOException e) {
- Log.e(TAG, e.getMessage(), e);
- throw new ErrnoException("onWrite", OsConstants.EIO);
- }
- }
-
- @Override
- public void onFsync() throws ErrnoException {
- tryFsync();
- }
-
- @Override
- public void onRelease() {
- try {
- tryFsync();
- } catch (ErrnoException error) {
- // Cannot recover from the error at onRelease. Client app should use fsync to
- // ensure the provider writes data correctly.
- Log.e(TAG, "Cannot recover from the error at onRelease.", error);
- } finally {
- if (mWriter != null) {
- IoUtils.closeQuietly(mWriter);
- }
- }
- }
-
- private void tryFsync() throws ErrnoException {
- try {
- if (mWriter != null) {
- final MtpDeviceRecord device =
- getDeviceToolkit(mDatabase.createIdentifier(
- mWriter.getDocumentId()).mDeviceId).mDeviceRecord;
- mWriter.flush(mMtpManager, mDatabase, device.operationsSupported);
- }
- } catch (IOException e) {
- Log.e(TAG, e.getMessage(), e);
- throw new ErrnoException("onWrite", OsConstants.EIO);
- }
- }
- }
-}
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsService.java b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsService.java
deleted file mode 100644
index fa1a12030..0000000
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsService.java
+++ /dev/null
@@ -1,124 +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.mtp;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.app.Notification;
-import android.app.Service;
-import android.app.NotificationManager;
-import android.content.Intent;
-import android.os.IBinder;
-import android.os.Parcelable;
-import android.service.notification.StatusBarNotification;
-import android.util.Log;
-import com.android.internal.util.Preconditions;
-import java.util.HashSet;
-import java.util.Set;
-
-/**
- * Service to manage lifetime of DocumentsProvider's process.
- * The service prevents the system from killing the process that holds USB connections. The service
- * starts to run when the first MTP device is opened, and stops when the last MTP device is closed.
- */
-public class MtpDocumentsService extends Service {
- static final String ACTION_UPDATE_NOTIFICATION = "com.android.mtp.UPDATE_NOTIFICATION";
- static final String EXTRA_DEVICE_IDS = "deviceIds";
- static final String EXTRA_DEVICE_NOTIFICATIONS = "deviceNotifications";
-
- private NotificationManager mNotificationManager;
-
- @Override
- public IBinder onBind(Intent intent) {
- // The service is used via intents.
- return null;
- }
-
- @Override
- public void onCreate() {
- super.onCreate();
- mNotificationManager = getSystemService(NotificationManager.class);
- }
-
- @Override
- public int onStartCommand(Intent intent, int flags, int startId) {
- // If intent is null, the service was restarted.
- if (intent == null || ACTION_UPDATE_NOTIFICATION.equals(intent.getAction())) {
- final int[] ids = intent.hasExtra(EXTRA_DEVICE_IDS) ?
- intent.getExtras().getIntArray(EXTRA_DEVICE_IDS) : null;
- final Notification[] notifications = intent.hasExtra(EXTRA_DEVICE_NOTIFICATIONS) ?
- castToNotifications(intent.getExtras().getParcelableArray(
- EXTRA_DEVICE_NOTIFICATIONS)) : null;
- return updateForegroundState(ids, notifications) ? START_STICKY : START_NOT_STICKY;
- }
- return START_NOT_STICKY;
- }
-
- /**
- * Updates the foreground state of the service.
- * @return Whether the service is foreground or not.
- */
- private boolean updateForegroundState(
- @Nullable int[] ids, @Nullable Notification[] notifications) {
- final Set<Integer> openedNotification = new HashSet<>();
- final int size = ids != null ? ids.length : 0;
- if (size != 0) {
- Preconditions.checkArgument(ids != null);
- Preconditions.checkArgument(notifications != null);
- Preconditions.checkArgument(ids.length == notifications.length);
- }
-
- for (int i = 0; i < size; i++) {
- if (i == 0) {
- // Mark this service as foreground with the notification so that the process is
- // not killed by the system while a MTP device is opened.
- startForeground(ids[i], notifications[i]);
- } else {
- // Only one notification can be shown as a foreground notification. We need to
- // show the rest as normal notification.
- mNotificationManager.notify(ids[i], notifications[i]);
- }
- openedNotification.add(ids[i]);
- }
-
- final StatusBarNotification[] activeNotifications =
- mNotificationManager.getActiveNotifications();
- for (final StatusBarNotification notification : activeNotifications) {
- if (!openedNotification.contains(notification.getId())) {
- mNotificationManager.cancel(notification.getId());
- }
- }
-
- if (size == 0) {
- // There is no opened device.
- stopForeground(true /* removeNotification */);
- stopSelf();
- return false;
- }
-
- return true;
- }
-
- private static @NonNull Notification[] castToNotifications(@NonNull Parcelable[] src) {
- Preconditions.checkNotNull(src);
- final Notification[] notifications = new Notification[src.length];
- for (int i = 0; i < src.length; i++) {
- notifications[i] = (Notification) src[i];
- }
- return notifications;
- }
-}
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpFileWriter.java b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpFileWriter.java
deleted file mode 100644
index 3e1bedc..0000000
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpFileWriter.java
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright (C) 2016 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.mtp;
-
-import android.content.Context;
-import android.mtp.MtpObjectInfo;
-import android.os.ParcelFileDescriptor;
-import android.system.ErrnoException;
-import android.system.Os;
-import android.system.OsConstants;
-
-import com.android.internal.util.Preconditions;
-
-import java.io.File;
-import java.io.IOException;
-
-class MtpFileWriter implements AutoCloseable {
- final ParcelFileDescriptor mCacheFd;
- final String mDocumentId;
- boolean mDirty;
-
- MtpFileWriter(Context context, String documentId) throws IOException {
- mDocumentId = documentId;
- mDirty = false;
- final File tempFile = File.createTempFile("mtp", "tmp", context.getCacheDir());
- mCacheFd = ParcelFileDescriptor.open(
- tempFile,
- ParcelFileDescriptor.MODE_READ_WRITE |
- ParcelFileDescriptor.MODE_TRUNCATE |
- ParcelFileDescriptor.MODE_CREATE);
- tempFile.delete();
- }
-
- String getDocumentId() {
- return mDocumentId;
- }
-
- int write(long offset, int size, byte[] bytes) throws IOException, ErrnoException {
- Preconditions.checkArgumentNonnegative(offset, "offset");
- Preconditions.checkArgumentNonnegative(size, "size");
- Preconditions.checkArgument(size <= bytes.length);
- if (size == 0) {
- return 0;
- }
- mDirty = true;
- Os.lseek(mCacheFd.getFileDescriptor(), offset, OsConstants.SEEK_SET);
- return Os.write(mCacheFd.getFileDescriptor(), bytes, 0, size);
- }
-
- void flush(MtpManager manager, MtpDatabase database, int[] operationsSupported)
- throws IOException, ErrnoException {
- // Skip unnecessary flush.
- if (!mDirty) {
- return;
- }
-
- // Get the placeholder object info.
- final Identifier identifier = database.createIdentifier(mDocumentId);
- final MtpObjectInfo placeholderObjectInfo =
- manager.getObjectInfo(identifier.mDeviceId, identifier.mObjectHandle);
-
- // Delete the target object info if it already exists (as a placeholder).
- manager.deleteDocument(identifier.mDeviceId, identifier.mObjectHandle);
-
- // Create the target object info with a correct file size and upload the file.
- final long size = Os.lseek(mCacheFd.getFileDescriptor(), 0, OsConstants.SEEK_END);
- final MtpObjectInfo targetObjectInfo = new MtpObjectInfo.Builder(placeholderObjectInfo)
- .setCompressedSize(size)
- .build();
-
- Os.lseek(mCacheFd.getFileDescriptor(), 0, OsConstants.SEEK_SET);
- final int newObjectHandle = manager.createDocument(
- identifier.mDeviceId, targetObjectInfo, mCacheFd);
-
- final MtpObjectInfo newObjectInfo = manager.getObjectInfo(
- identifier.mDeviceId, newObjectHandle);
- final Identifier parentIdentifier =
- database.getParentIdentifier(identifier.mDocumentId);
- database.updateObject(
- identifier.mDocumentId,
- identifier.mDeviceId,
- parentIdentifier.mDocumentId,
- operationsSupported,
- newObjectInfo,
- size);
-
- mDirty = false;
- }
-
- @Override
- public void close() throws IOException {
- mCacheFd.close();
- }
-}
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpManager.java b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpManager.java
deleted file mode 100644
index a7de631..0000000
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpManager.java
+++ /dev/null
@@ -1,321 +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.mtp;
-
-import android.annotation.Nullable;
-import android.content.Context;
-import android.hardware.usb.UsbConstants;
-import android.hardware.usb.UsbDevice;
-import android.hardware.usb.UsbDeviceConnection;
-import android.hardware.usb.UsbInterface;
-import android.hardware.usb.UsbManager;
-import android.mtp.MtpConstants;
-import android.mtp.MtpDevice;
-import android.mtp.MtpDeviceInfo;
-import android.mtp.MtpEvent;
-import android.mtp.MtpObjectInfo;
-import android.mtp.MtpStorageInfo;
-import android.os.CancellationSignal;
-import android.os.ParcelFileDescriptor;
-import android.util.Log;
-import android.util.SparseArray;
-
-import com.android.internal.annotations.VisibleForTesting;
-
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.util.ArrayList;
-
-/**
- * The model wrapping android.mtp API.
- */
-class MtpManager {
- final static int OBJECT_HANDLE_ROOT_CHILDREN = -1;
-
- /**
- * Subclass for PTP.
- */
- private static final int SUBCLASS_STILL_IMAGE_CAPTURE = 1;
-
- /**
- * Subclass for Android style MTP.
- */
- private static final int SUBCLASS_MTP = 0xff;
-
- /**
- * Protocol for Picture Transfer Protocol (PIMA 15470).
- */
- private static final int PROTOCOL_PICTURE_TRANSFER = 1;
-
- /**
- * Protocol for Android style MTP.
- */
- private static final int PROTOCOL_MTP = 0;
-
- private final UsbManager mManager;
- private final SparseArray<MtpDevice> mDevices = new SparseArray<>();
-
- MtpManager(Context context) {
- mManager = (UsbManager) context.getSystemService(Context.USB_SERVICE);
- }
-
- synchronized MtpDeviceRecord openDevice(int deviceId) throws IOException {
- UsbDevice rawDevice = null;
- for (final UsbDevice candidate : mManager.getDeviceList().values()) {
- if (candidate.getDeviceId() == deviceId) {
- rawDevice = candidate;
- break;
- }
- }
-
- ensureNotNull(rawDevice, "Not found USB device: " + deviceId);
-
- if (!mManager.hasPermission(rawDevice)) {
- mManager.grantPermission(rawDevice);
- if (!mManager.hasPermission(rawDevice)) {
- throw new IOException("Failed to grant a device permission.");
- }
- }
-
- final MtpDevice device = new MtpDevice(rawDevice);
-
- final UsbDeviceConnection connection = ensureNotNull(
- mManager.openDevice(rawDevice),
- "Failed to open a USB connection.");
-
- if (!device.open(connection)) {
- // We cannot open connection when another application use the device.
- throw new BusyDeviceException();
- }
-
- // Handle devices that fail to obtain storages just after opening a MTP session.
- final int[] storageIds = ensureNotNull(
- device.getStorageIds(),
- "Not found MTP storages in the device.");
-
- mDevices.put(deviceId, device);
- return createDeviceRecord(rawDevice);
- }
-
- synchronized void closeDevice(int deviceId) throws IOException {
- getDevice(deviceId).close();
- mDevices.remove(deviceId);
- }
-
- synchronized MtpDeviceRecord[] getDevices() {
- final ArrayList<MtpDeviceRecord> devices = new ArrayList<>();
- for (UsbDevice device : mManager.getDeviceList().values()) {
- if (!isMtpDevice(device)) {
- continue;
- }
- devices.add(createDeviceRecord(device));
- }
- return devices.toArray(new MtpDeviceRecord[devices.size()]);
- }
-
- MtpObjectInfo getObjectInfo(int deviceId, int objectHandle) throws IOException {
- final MtpDevice device = getDevice(deviceId);
- synchronized (device) {
- return ensureNotNull(
- device.getObjectInfo(objectHandle),
- "Failed to get object info: " + objectHandle);
- }
- }
-
- int[] getObjectHandles(int deviceId, int storageId, int parentObjectHandle)
- throws IOException {
- final MtpDevice device = getDevice(deviceId);
- synchronized (device) {
- return ensureNotNull(
- device.getObjectHandles(storageId, 0 /* all format */, parentObjectHandle),
- "Failed to fetch object handles.");
- }
- }
-
- byte[] getObject(int deviceId, int objectHandle, int expectedSize)
- throws IOException {
- final MtpDevice device = getDevice(deviceId);
- synchronized (device) {
- return ensureNotNull(
- device.getObject(objectHandle, expectedSize),
- "Failed to fetch object bytes");
- }
- }
-
- long getPartialObject(int deviceId, int objectHandle, long offset, long size, byte[] buffer)
- throws IOException {
- final MtpDevice device = getDevice(deviceId);
- synchronized (device) {
- return device.getPartialObject(objectHandle, offset, size, buffer);
- }
- }
-
- long getPartialObject64(int deviceId, int objectHandle, long offset, long size, byte[] buffer)
- throws IOException {
- final MtpDevice device = getDevice(deviceId);
- synchronized (device) {
- return device.getPartialObject64(objectHandle, offset, size, buffer);
- }
- }
-
- byte[] getThumbnail(int deviceId, int objectHandle) throws IOException {
- final MtpDevice device = getDevice(deviceId);
- synchronized (device) {
- return ensureNotNull(
- device.getThumbnail(objectHandle),
- "Failed to obtain thumbnail bytes");
- }
- }
-
- void deleteDocument(int deviceId, int objectHandle) throws IOException {
- final MtpDevice device = getDevice(deviceId);
- synchronized (device) {
- if (!device.deleteObject(objectHandle)) {
- throw new IOException("Failed to delete document");
- }
- }
- }
-
- int createDocument(int deviceId, MtpObjectInfo objectInfo,
- ParcelFileDescriptor source) throws IOException {
- final MtpDevice device = getDevice(deviceId);
- synchronized (device) {
- final MtpObjectInfo sendObjectInfoResult = device.sendObjectInfo(objectInfo);
- if (sendObjectInfoResult == null) {
- throw new SendObjectInfoFailure();
- }
- if (objectInfo.getFormat() != MtpConstants.FORMAT_ASSOCIATION) {
- if (!device.sendObject(sendObjectInfoResult.getObjectHandle(),
- sendObjectInfoResult.getCompressedSizeLong(), source)) {
- throw new IOException("Failed to send contents of a document");
- }
- }
- return sendObjectInfoResult.getObjectHandle();
- }
- }
-
- int getParent(int deviceId, int objectHandle) throws IOException {
- final MtpDevice device = getDevice(deviceId);
- synchronized (device) {
- final int result = (int) device.getParent(objectHandle);
- if (result == 0xffffffff) {
- throw new FileNotFoundException("Not found parent object");
- }
- return result;
- }
- }
-
- void importFile(int deviceId, int objectHandle, ParcelFileDescriptor target)
- throws IOException {
- final MtpDevice device = getDevice(deviceId);
- synchronized (device) {
- if (!device.importFile(objectHandle, target)) {
- throw new IOException("Failed to import file to FD");
- }
- }
- }
-
- @VisibleForTesting
- MtpEvent readEvent(int deviceId, CancellationSignal signal) throws IOException {
- final MtpDevice device = getDevice(deviceId);
- return device.readEvent(signal);
- }
-
- long getObjectSizeLong(int deviceId, int objectHandle, int format) throws IOException {
- final MtpDevice device = getDevice(deviceId);
- return device.getObjectSizeLong(objectHandle, format);
- }
-
- private synchronized MtpDevice getDevice(int deviceId) throws IOException {
- return ensureNotNull(
- mDevices.get(deviceId),
- "USB device " + deviceId + " is not opened.");
- }
-
- private MtpRoot[] getRoots(int deviceId) throws IOException {
- final MtpDevice device = getDevice(deviceId);
- synchronized (device) {
- final int[] storageIds =
- ensureNotNull(device.getStorageIds(), "Failed to obtain storage IDs.");
- final ArrayList<MtpRoot> roots = new ArrayList<>();
- for (int i = 0; i < storageIds.length; i++) {
- final MtpStorageInfo info = device.getStorageInfo(storageIds[i]);
- if (info == null) {
- continue;
- }
- roots.add(new MtpRoot(device.getDeviceId(), info));
- }
- return roots.toArray(new MtpRoot[roots.size()]);
- }
- }
-
- private MtpDeviceRecord createDeviceRecord(UsbDevice device) {
- final MtpDevice mtpDevice = mDevices.get(device.getDeviceId());
- final boolean opened = mtpDevice != null;
- final String name = device.getProductName();
- MtpRoot[] roots;
- int[] operationsSupported = null;
- int[] eventsSupported = null;
- if (opened) {
- try {
- roots = getRoots(device.getDeviceId());
- } catch (IOException exp) {
- Log.e(MtpDocumentsProvider.TAG, "Failed to open device", exp);
- // If we failed to fetch roots for the device, we still returns device model
- // with an empty set of roots so that the device is shown DocumentsUI as long as
- // the device is physically connected.
- roots = new MtpRoot[0];
- }
- final MtpDeviceInfo info = mtpDevice.getDeviceInfo();
- if (info != null) {
- operationsSupported = info.getOperationsSupported();
- eventsSupported = info.getEventsSupported();
- }
- } else {
- roots = new MtpRoot[0];
- }
- return new MtpDeviceRecord(
- device.getDeviceId(), name, device.getSerialNumber(), opened, roots,
- operationsSupported, eventsSupported);
- }
-
- static boolean isMtpDevice(UsbDevice device) {
- for (int i = 0; i < device.getInterfaceCount(); i++) {
- final UsbInterface usbInterface = device.getInterface(i);
- if ((usbInterface.getInterfaceClass() == UsbConstants.USB_CLASS_STILL_IMAGE &&
- usbInterface.getInterfaceSubclass() == SUBCLASS_STILL_IMAGE_CAPTURE &&
- usbInterface.getInterfaceProtocol() == PROTOCOL_PICTURE_TRANSFER)) {
- return true;
- }
- if (usbInterface.getInterfaceClass() == UsbConstants.USB_SUBCLASS_VENDOR_SPEC &&
- usbInterface.getInterfaceSubclass() == SUBCLASS_MTP &&
- usbInterface.getInterfaceProtocol() == PROTOCOL_MTP &&
- "MTP".equals(usbInterface.getName())) {
- return true;
- }
- }
- return false;
- }
-
- private static <T> T ensureNotNull(@Nullable T t, String errorMessage) throws IOException {
- if (t != null) {
- return t;
- } else {
- throw new IOException(errorMessage);
- }
- }
-}
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpRoot.java b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpRoot.java
deleted file mode 100644
index 8530aaf..0000000
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpRoot.java
+++ /dev/null
@@ -1,78 +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.mtp;
-
-import android.mtp.MtpStorageInfo;
-
-import com.android.internal.annotations.VisibleForTesting;
-
-class MtpRoot {
- final int mDeviceId;
- final int mStorageId;
- final String mDescription;
- final long mFreeSpace;
- final long mMaxCapacity;
- final String mVolumeIdentifier;
-
- @VisibleForTesting
- MtpRoot(int deviceId,
- int storageId,
- String description,
- long freeSpace,
- long maxCapacity,
- String volumeIdentifier) {
- mDeviceId = deviceId;
- mStorageId = storageId;
- mDescription = description;
- mFreeSpace = freeSpace;
- mMaxCapacity = maxCapacity;
- mVolumeIdentifier = volumeIdentifier;
- }
-
- MtpRoot(int deviceId, MtpStorageInfo storageInfo) {
- mDeviceId = deviceId;
- mStorageId = storageInfo.getStorageId();
- mDescription = storageInfo.getDescription();
- mFreeSpace = storageInfo.getFreeSpace();
- mMaxCapacity = storageInfo.getMaxCapacity();
- mVolumeIdentifier = storageInfo.getVolumeIdentifier();
- }
-
- @Override
- public boolean equals(Object object) {
- if (!(object instanceof MtpRoot))
- return false;
- final MtpRoot other = (MtpRoot) object;
- return mDeviceId == other.mDeviceId &&
- mStorageId == other.mStorageId &&
- mDescription.equals(other.mDescription) &&
- mFreeSpace == other.mFreeSpace &&
- mMaxCapacity == other.mMaxCapacity &&
- mVolumeIdentifier.equals(other.mVolumeIdentifier);
- }
-
- @Override
- public int hashCode() {
- return mDeviceId ^ mStorageId ^ mDescription.hashCode() ^
- ((int) mFreeSpace) ^ ((int) mMaxCapacity) ^ mVolumeIdentifier.hashCode();
- }
-
- @Override
- public String toString() {
- return "MtpRoot{Name: " + mDescription + "}";
- }
-}
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/PipeManager.java b/packages/MtpDocumentsProvider/src/com/android/mtp/PipeManager.java
deleted file mode 100644
index 795bbc1..0000000
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/PipeManager.java
+++ /dev/null
@@ -1,121 +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.mtp;
-
-import android.os.ParcelFileDescriptor;
-import android.util.Log;
-
-import java.io.IOException;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.TimeUnit;
-
-class PipeManager {
- /**
- * Milliseconds we wait for background thread when pausing.
- */
- private final static long AWAIT_TERMINATION_TIMEOUT = 2000;
-
- final ExecutorService mExecutor;
- final MtpDatabase mDatabase;
-
- PipeManager(MtpDatabase database) {
- this(database, Executors.newSingleThreadExecutor());
- }
-
- PipeManager(MtpDatabase database, ExecutorService executor) {
- this.mDatabase = database;
- this.mExecutor = executor;
- }
-
- ParcelFileDescriptor readDocument(MtpManager model, Identifier identifier) throws IOException {
- final Task task = new ImportFileTask(model, identifier);
- mExecutor.execute(task);
- return task.getReadingFileDescriptor();
- }
-
- ParcelFileDescriptor readThumbnail(MtpManager model, Identifier identifier) throws IOException {
- final Task task = new GetThumbnailTask(model, identifier);
- mExecutor.execute(task);
- return task.getReadingFileDescriptor();
- }
-
- private static abstract class Task implements Runnable {
- protected final MtpManager mManager;
- protected final Identifier mIdentifier;
- protected final ParcelFileDescriptor[] mDescriptors;
-
- Task(MtpManager manager, Identifier identifier) throws IOException {
- mManager = manager;
- mIdentifier = identifier;
- mDescriptors = ParcelFileDescriptor.createReliablePipe();
- }
-
- ParcelFileDescriptor getReadingFileDescriptor() {
- return mDescriptors[0];
- }
- }
-
- private static class ImportFileTask extends Task {
- ImportFileTask(MtpManager model, Identifier identifier) throws IOException {
- super(model, identifier);
- }
-
- @Override
- public void run() {
- try {
- mManager.importFile(
- mIdentifier.mDeviceId, mIdentifier.mObjectHandle, mDescriptors[1]);
- mDescriptors[1].close();
- } catch (IOException error) {
- try {
- mDescriptors[1].closeWithError("Failed to stream a file.");
- } catch (IOException closeError) {
- Log.w(MtpDocumentsProvider.TAG, closeError.getMessage());
- }
- }
- }
- }
-
- private static class GetThumbnailTask extends Task {
- GetThumbnailTask(MtpManager model, Identifier identifier) throws IOException {
- super(model, identifier);
- }
-
- @Override
- public void run() {
- try {
- try (final ParcelFileDescriptor.AutoCloseOutputStream stream =
- new ParcelFileDescriptor.AutoCloseOutputStream(mDescriptors[1])) {
- try {
- stream.write(mManager.getThumbnail(
- mIdentifier.mDeviceId, mIdentifier.mObjectHandle));
- } catch (IOException error) {
- mDescriptors[1].closeWithError("Failed to stream a thumbnail.");
- }
- }
- } catch (IOException closeError) {
- Log.w(MtpDocumentsProvider.TAG, closeError.getMessage());
- }
- }
- }
-
- boolean close() throws InterruptedException {
- mExecutor.shutdownNow();
- return mExecutor.awaitTermination(AWAIT_TERMINATION_TIMEOUT, TimeUnit.MILLISECONDS);
- }
-}
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/ReceiverActivity.java b/packages/MtpDocumentsProvider/src/com/android/mtp/ReceiverActivity.java
deleted file mode 100644
index 19c2c14..0000000
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/ReceiverActivity.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2016 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.mtp;
-
-import android.app.Activity;
-import android.content.Intent;
-import android.hardware.usb.UsbDevice;
-import android.hardware.usb.UsbManager;
-import android.net.Uri;
-import android.os.Bundle;
-import android.provider.DocumentsContract;
-import android.util.Log;
-
-import java.io.IOException;
-
-/**
- * Invisible activity to receive intents.
- * To show Files app for the UsbManager.ACTION_USB_DEVICE_ATTACHED intent, the intent should be
- * received by activity. The activity has NoDisplay theme and immediately terminate after routing
- * intent to DocumentsUI.
- */
-public class ReceiverActivity extends Activity {
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- if (UsbManager.ACTION_USB_DEVICE_ATTACHED.equals(getIntent().getAction())) {
- final UsbDevice device = getIntent().getParcelableExtra(UsbManager.EXTRA_DEVICE);
- try {
- final MtpDocumentsProvider provider = MtpDocumentsProvider.getInstance();
- provider.openDevice(device.getDeviceId());
- final String deviceRootId = provider.getDeviceDocumentId(device.getDeviceId());
- final Uri uri = DocumentsContract.buildRootUri(
- MtpDocumentsProvider.AUTHORITY, deviceRootId);
-
- final Intent intent = new Intent(Intent.ACTION_VIEW);
- intent.setDataAndType(uri, DocumentsContract.Root.MIME_TYPE_ITEM);
- intent.addCategory(Intent.CATEGORY_DEFAULT);
- this.startActivity(intent);
- } catch (IOException exception) {
- Log.e(MtpDocumentsProvider.TAG, "Failed to open device", exception);
- }
- }
- finish();
- }
-}
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/RootScanner.java b/packages/MtpDocumentsProvider/src/com/android/mtp/RootScanner.java
deleted file mode 100644
index 20be2ba..0000000
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/RootScanner.java
+++ /dev/null
@@ -1,200 +0,0 @@
-/*
- * Copyright (C) 2016 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.mtp;
-
-import android.content.ContentResolver;
-import android.net.Uri;
-import android.os.Process;
-import android.provider.DocumentsContract;
-import android.util.Log;
-
-import java.io.FileNotFoundException;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
-
-final class RootScanner {
- /**
- * Polling interval in milliseconds used for first SHORT_POLLING_TIMES because it is more
- * likely to add new root just after the device is added.
- */
- private final static long SHORT_POLLING_INTERVAL = 2000;
-
- /**
- * Polling interval in milliseconds for low priority polling, when changes are not expected.
- */
- private final static long LONG_POLLING_INTERVAL = 30 * 1000;
-
- /**
- * @see #SHORT_POLLING_INTERVAL
- */
- private final static long SHORT_POLLING_TIMES = 10;
-
- /**
- * Milliseconds we wait for background thread when pausing.
- */
- private final static long AWAIT_TERMINATION_TIMEOUT = 2000;
-
- final ContentResolver mResolver;
- final MtpManager mManager;
- final MtpDatabase mDatabase;
-
- ExecutorService mExecutor;
- private UpdateRootsRunnable mCurrentTask;
-
- RootScanner(
- ContentResolver resolver,
- MtpManager manager,
- MtpDatabase database) {
- mResolver = resolver;
- mManager = manager;
- mDatabase = database;
- }
-
- /**
- * Notifies a change of the roots list via ContentResolver.
- */
- void notifyChange() {
- final Uri uri = DocumentsContract.buildRootsUri(MtpDocumentsProvider.AUTHORITY);
- mResolver.notifyChange(uri, null, false);
- }
-
- /**
- * Starts to check new changes right away.
- */
- synchronized CountDownLatch resume() {
- if (mExecutor == null) {
- // Only single thread updates the database.
- mExecutor = Executors.newSingleThreadExecutor();
- }
- if (mCurrentTask != null) {
- // Stop previous task.
- mCurrentTask.stop();
- }
- mCurrentTask = new UpdateRootsRunnable();
- mExecutor.execute(mCurrentTask);
- return mCurrentTask.mFirstScanCompleted;
- }
-
- /**
- * Stops background thread and wait for its termination.
- * @throws InterruptedException
- */
- synchronized void pause() throws InterruptedException, TimeoutException {
- if (mExecutor == null) {
- return;
- }
- mExecutor.shutdownNow();
- try {
- if (!mExecutor.awaitTermination(AWAIT_TERMINATION_TIMEOUT, TimeUnit.MILLISECONDS)) {
- throw new TimeoutException(
- "Timeout for terminating RootScanner's background thread.");
- }
- } finally {
- mExecutor = null;
- }
- }
-
- /**
- * Runnable to scan roots and update the database information.
- */
- private final class UpdateRootsRunnable implements Runnable {
- /**
- * Count down latch that specifies the runnable is stopped.
- */
- final CountDownLatch mStopped = new CountDownLatch(1);
-
- /**
- * Count down latch that specifies the first scan is completed.
- */
- final CountDownLatch mFirstScanCompleted = new CountDownLatch(1);
-
- @Override
- public void run() {
- Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
- int pollingCount = 0;
- while (mStopped.getCount() > 0) {
- boolean changed = false;
-
- // Update devices.
- final MtpDeviceRecord[] devices = mManager.getDevices();
- try {
- mDatabase.getMapper().startAddingDocuments(null /* parentDocumentId */);
- for (final MtpDeviceRecord device : devices) {
- if (mDatabase.getMapper().putDeviceDocument(device)) {
- changed = true;
- }
- }
- if (mDatabase.getMapper().stopAddingDocuments(
- null /* parentDocumentId */)) {
- changed = true;
- }
- } catch (FileNotFoundException exception) {
- // The top root (ID is null) must exist always.
- // FileNotFoundException is unexpected.
- Log.e(MtpDocumentsProvider.TAG, "Unexpected FileNotFoundException", exception);
- throw new AssertionError("Unexpected exception for the top parent", exception);
- }
-
- // Update roots.
- for (final MtpDeviceRecord device : devices) {
- final String documentId = mDatabase.getDocumentIdForDevice(device.deviceId);
- if (documentId == null) {
- continue;
- }
- try {
- mDatabase.getMapper().startAddingDocuments(documentId);
- if (mDatabase.getMapper().putStorageDocuments(
- documentId, device.operationsSupported, device.roots)) {
- changed = true;
- }
- if (mDatabase.getMapper().stopAddingDocuments(documentId)) {
- changed = true;
- }
- } catch (FileNotFoundException exception) {
- Log.e(MtpDocumentsProvider.TAG, "Parent document is gone.", exception);
- continue;
- }
- }
-
- if (changed) {
- notifyChange();
- }
- mFirstScanCompleted.countDown();
- pollingCount++;
- if (devices.length == 0) {
- break;
- }
- try {
- // Use SHORT_POLLING_PERIOD for the first SHORT_POLLING_TIMES because it is
- // more likely to add new root just after the device is added.
- // TODO: Use short interval only for a device that is just added.
- mStopped.await(pollingCount > SHORT_POLLING_TIMES ?
- LONG_POLLING_INTERVAL : SHORT_POLLING_INTERVAL, TimeUnit.MILLISECONDS);
- } catch (InterruptedException exp) {
- break;
- }
- }
- }
-
- void stop() {
- mStopped.countDown();
- }
- }
-}
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/SendObjectInfoFailure.java b/packages/MtpDocumentsProvider/src/com/android/mtp/SendObjectInfoFailure.java
deleted file mode 100644
index db7d777..0000000
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/SendObjectInfoFailure.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (C) 2016 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.mtp;
-
-import java.io.IOException;
-
-/**
- * Exception thrown when sendObjectInfo failed.
- */
-class SendObjectInfoFailure extends IOException {
- SendObjectInfoFailure() {
- super("Failed to MtpDevice#sendObjectInfo.");
- }
-}
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/ServiceIntentSender.java b/packages/MtpDocumentsProvider/src/com/android/mtp/ServiceIntentSender.java
deleted file mode 100644
index 629f6df..0000000
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/ServiceIntentSender.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (C) 2016 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.mtp;
-
-import android.annotation.NonNull;
-import android.app.Notification;
-import android.app.NotificationChannel;
-import android.app.NotificationManager;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.Preconditions;
-
-/**
- * Sends intent to MtpDocumentsService.
- */
-class ServiceIntentSender {
- private final static String CHANNEL_ID = "device_notification_channel";
- private final Context mContext;
-
- ServiceIntentSender(Context context) {
- mContext = context;
-
- // Create notification channel.
- final NotificationChannel mChannel = new NotificationChannel(
- CHANNEL_ID,
- context.getResources().getString(
- com.android.internal.R.string.default_notification_channel_label),
- NotificationManager.IMPORTANCE_LOW);
- final NotificationManager notificationManager =
- (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
- notificationManager.createNotificationChannel(mChannel);
- }
-
- @VisibleForTesting
- protected ServiceIntentSender() {
- mContext = null;
- }
-
- /**
- * Notify the change of opened device set.
- * @param records List of opened devices. Can be empty.
- */
- void sendUpdateNotificationIntent(@NonNull MtpDeviceRecord[] records) {
- Preconditions.checkNotNull(records);
- final Intent intent = new Intent(MtpDocumentsService.ACTION_UPDATE_NOTIFICATION);
- intent.setComponent(new ComponentName(mContext, MtpDocumentsService.class));
- if (records.length != 0) {
- final int[] ids = new int[records.length];
- final Notification[] notifications = new Notification[records.length];
- for (int i = 0; i < records.length; i++) {
- ids[i] = records[i].deviceId;
- notifications[i] = createNotification(mContext, records[i]);
- }
- intent.putExtra(MtpDocumentsService.EXTRA_DEVICE_IDS, ids);
- intent.putExtra(MtpDocumentsService.EXTRA_DEVICE_NOTIFICATIONS, notifications);
- mContext.startForegroundService(intent);
- } else {
- mContext.startService(intent);
- }
- }
-
- private static Notification createNotification(Context context, MtpDeviceRecord device) {
- final String title = context.getResources().getString(
- R.string.accessing_notification_title,
- device.name);
- return new Notification.Builder(context, CHANNEL_ID)
- .setLocalOnly(true)
- .setContentTitle(title)
- .setSmallIcon(com.android.internal.R.drawable.stat_sys_data_usb)
- .setCategory(Notification.CATEGORY_SYSTEM)
- .setFlag(Notification.FLAG_NO_CLEAR, true)
- .build();
- }
-}
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/UsbIntentReceiver.java b/packages/MtpDocumentsProvider/src/com/android/mtp/UsbIntentReceiver.java
deleted file mode 100644
index 0489ea8..0000000
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/UsbIntentReceiver.java
+++ /dev/null
@@ -1,45 +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.mtp;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.hardware.usb.UsbDevice;
-import android.hardware.usb.UsbManager;
-import android.util.Log;
-
-import java.io.IOException;
-
-public class UsbIntentReceiver extends BroadcastReceiver {
- @Override
- public void onReceive(Context context, Intent intent) {
- final UsbDevice device = intent.getExtras().getParcelable(UsbManager.EXTRA_DEVICE);
- switch (intent.getAction()) {
- case UsbManager.ACTION_USB_DEVICE_ATTACHED:
- MtpDocumentsProvider.getInstance().resumeRootScanner();
- break;
- case UsbManager.ACTION_USB_DEVICE_DETACHED:
- try {
- MtpDocumentsProvider.getInstance().closeDevice(device.getDeviceId());
- } catch (IOException | InterruptedException e) {
- Log.e(MtpDocumentsProvider.TAG, "Failed to close device", e);
- }
- break;
- }
- }
-}
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/annotations/UsedByNative.java b/packages/MtpDocumentsProvider/src/com/android/mtp/annotations/UsedByNative.java
deleted file mode 100644
index 2ded925..0000000
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/annotations/UsedByNative.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2016 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.mtp.annotations;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Target;
-
-/**
- * Annotation that shows the method is used by JNI.
- */
-@Target({ElementType.METHOD, ElementType.FIELD})
-public @interface UsedByNative {
- /**
- * JNI file name that uses the method.
- */
- String value();
-}
diff --git a/packages/MtpDocumentsProvider/tests/Android.mk b/packages/MtpDocumentsProvider/tests/Android.mk
deleted file mode 100644
index 11daac3..0000000
--- a/packages/MtpDocumentsProvider/tests/Android.mk
+++ /dev/null
@@ -1,14 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_JAVA_LIBRARIES := android.test.runner android.test.base android.test.mock
-LOCAL_STATIC_JAVA_LIBRARIES := junit
-LOCAL_PACKAGE_NAME := MtpDocumentsProviderTests
-LOCAL_PRIVATE_PLATFORM_APIS := true
-LOCAL_INSTRUMENTATION_FOR := MtpDocumentsProvider
-LOCAL_CERTIFICATE := media
-LOCAL_COMPATIBILITY_SUITE := device-tests
-
-include $(BUILD_PACKAGE)
diff --git a/packages/MtpDocumentsProvider/tests/AndroidManifest.xml b/packages/MtpDocumentsProvider/tests/AndroidManifest.xml
deleted file mode 100644
index e1307e9..0000000
--- a/packages/MtpDocumentsProvider/tests/AndroidManifest.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.mtp.tests"
- android:sharedUserId="android.media">
-
- <application>
- <uses-library android:name="android.test.runner" />
- <activity android:name="com.android.mtp.TestResultActivity"
- android:screenOrientation="locked"
- android:launchMode="singleInstance">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.LAUNCHER" />
- </intent-filter>
- </activity>
- </application>
-
- <instrumentation android:name="com.android.mtp.TestResultInstrumentation"
- android:targetPackage="com.android.mtp"
- android:label="Tests for MtpDocumentsProvider with the UI for output." />
-</manifest>
diff --git a/packages/MtpDocumentsProvider/tests/AndroidTest.xml b/packages/MtpDocumentsProvider/tests/AndroidTest.xml
deleted file mode 100644
index f84131c..0000000
--- a/packages/MtpDocumentsProvider/tests/AndroidTest.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2017 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<configuration description="Runs Tests for MtpDocumentsProvider with the UI for output.">
- <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
- <option name="test-file-name" value="MtpDocumentsProviderTests.apk" />
- </target_preparer>
-
- <option name="test-suite-tag" value="apct" />
- <option name="test-tag" value="MtpDocumentsProviderTests" />
- <test class="com.android.tradefed.testtype.InstrumentationTest" >
- <option name="package" value="com.android.mtp.tests" />
- <option name="runner" value="com.android.mtp.TestResultInstrumentation" />
- <option name="hidden-api-checks" value="false"/>
- </test>
-</configuration>
diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/DocumentLoaderTest.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/DocumentLoaderTest.java
deleted file mode 100644
index a3c6bd7..0000000
--- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/DocumentLoaderTest.java
+++ /dev/null
@@ -1,229 +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.mtp;
-
-import android.content.Context;
-import android.database.Cursor;
-import android.mtp.MtpObjectInfo;
-import android.net.Uri;
-import android.provider.DocumentsContract;
-import android.provider.DocumentsContract.Document;
-import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.MediumTest;
-
-import java.io.IOException;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeoutException;
-
-@MediumTest
-public class DocumentLoaderTest extends AndroidTestCase {
- private MtpDatabase mDatabase;
- private BlockableTestMtpManager mManager;
- private TestContentResolver mResolver;
- private DocumentLoader mLoader;
- final private Identifier mParentIdentifier = new Identifier(
- 0, 0, 0, "2", MtpDatabaseConstants.DOCUMENT_TYPE_STORAGE);
-
- @Override
- public void setUp() throws Exception {
- mDatabase = new MtpDatabase(getContext(), MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
-
- mDatabase.getMapper().startAddingDocuments(null);
- mDatabase.getMapper().putDeviceDocument(
- new MtpDeviceRecord(0, "Device", null, true, new MtpRoot[0], null, null));
- mDatabase.getMapper().stopAddingDocuments(null);
-
- mDatabase.getMapper().startAddingDocuments("1");
- mDatabase.getMapper().putStorageDocuments("1", new int[0], new MtpRoot[] {
- new MtpRoot(0, 0, "Storage", 1000, 1000, "")
- });
- mDatabase.getMapper().stopAddingDocuments("1");
-
- mManager = new BlockableTestMtpManager(getContext());
- mResolver = new TestContentResolver();
- }
-
- @Override
- public void tearDown() throws Exception {
- mLoader.close();
- mDatabase.close();
- }
-
- public void testBasic() throws Exception {
- setUpLoader();
-
- final Uri uri = DocumentsContract.buildChildDocumentsUri(
- MtpDocumentsProvider.AUTHORITY, mParentIdentifier.mDocumentId);
- setUpDocument(mManager, 40);
- mManager.blockDocument(0, 15);
- mManager.blockDocument(0, 35);
-
- {
- final Cursor cursor = mLoader.queryChildDocuments(
- MtpDocumentsProvider.DEFAULT_DOCUMENT_PROJECTION, mParentIdentifier);
- assertEquals(DocumentLoader.NUM_INITIAL_ENTRIES, cursor.getCount());
- }
-
- Thread.sleep(DocumentLoader.NOTIFY_PERIOD_MS);
- mManager.unblockDocument(0, 15);
- mResolver.waitForNotification(uri, 1);
-
- {
- final Cursor cursor = mLoader.queryChildDocuments(
- MtpDocumentsProvider.DEFAULT_DOCUMENT_PROJECTION, mParentIdentifier);
- assertEquals(
- DocumentLoader.NUM_INITIAL_ENTRIES + DocumentLoader.NUM_LOADING_ENTRIES,
- cursor.getCount());
- }
-
- mManager.unblockDocument(0, 35);
- mResolver.waitForNotification(uri, 2);
-
- {
- final Cursor cursor = mLoader.queryChildDocuments(
- MtpDocumentsProvider.DEFAULT_DOCUMENT_PROJECTION, mParentIdentifier);
- assertEquals(40, cursor.getCount());
- }
-
- assertEquals(2, mResolver.getChangeCount(uri));
- }
-
- public void testError_GetObjectHandles() throws Exception {
- mManager = new BlockableTestMtpManager(getContext()) {
- @Override
- int[] getObjectHandles(int deviceId, int storageId, int parentObjectHandle)
- throws IOException {
- throw new IOException();
- }
- };
- setUpLoader();
- mManager.setObjectHandles(0, 0, MtpManager.OBJECT_HANDLE_ROOT_CHILDREN, null);
- try {
- try (final Cursor cursor = mLoader.queryChildDocuments(
- MtpDocumentsProvider.DEFAULT_DOCUMENT_PROJECTION, mParentIdentifier)) {}
- fail();
- } catch (IOException exception) {
- // Expect exception.
- }
- }
-
- public void testError_GetObjectInfo() throws Exception {
- mManager = new BlockableTestMtpManager(getContext()) {
- @Override
- MtpObjectInfo getObjectInfo(int deviceId, int objectHandle) throws IOException {
- if (objectHandle == DocumentLoader.NUM_INITIAL_ENTRIES) {
- throw new IOException();
- } else {
- return super.getObjectInfo(deviceId, objectHandle);
- }
- }
- };
- setUpLoader();
- setUpDocument(mManager, DocumentLoader.NUM_INITIAL_ENTRIES);
- try (final Cursor cursor = mLoader.queryChildDocuments(
- MtpDocumentsProvider.DEFAULT_DOCUMENT_PROJECTION, mParentIdentifier)) {
- // Even if MtpManager returns an error for a document, loading must complete.
- assertFalse(cursor.getExtras().getBoolean(DocumentsContract.EXTRA_LOADING));
- }
- }
-
- public void testCancelTask() throws IOException, InterruptedException, TimeoutException {
- setUpDocument(mManager,
- DocumentLoader.NUM_INITIAL_ENTRIES + 1);
-
- // Block the first iteration in the background thread.
- mManager.blockDocument(
- 0, DocumentLoader.NUM_INITIAL_ENTRIES + 1);
- setUpLoader();
- try (final Cursor cursor = mLoader.queryChildDocuments(
- MtpDocumentsProvider.DEFAULT_DOCUMENT_PROJECTION, mParentIdentifier)) {
- assertTrue(cursor.getExtras().getBoolean(DocumentsContract.EXTRA_LOADING));
- }
-
- final Uri uri = DocumentsContract.buildChildDocumentsUri(
- MtpDocumentsProvider.AUTHORITY, mParentIdentifier.mDocumentId);
- assertEquals(0, mResolver.getChangeCount(uri));
-
- // Clear task while the first iteration is being blocked.
- mLoader.cancelTask(mParentIdentifier);
- mManager.unblockDocument(
- 0, DocumentLoader.NUM_INITIAL_ENTRIES + 1);
- Thread.sleep(DocumentLoader.NOTIFY_PERIOD_MS);
- assertEquals(0, mResolver.getChangeCount(uri));
-
- // Check if it's OK to query invalidated task.
- try (final Cursor cursor = mLoader.queryChildDocuments(
- MtpDocumentsProvider.DEFAULT_DOCUMENT_PROJECTION, mParentIdentifier)) {
- assertTrue(cursor.getExtras().getBoolean(DocumentsContract.EXTRA_LOADING));
- }
- mResolver.waitForNotification(uri, 1);
- }
-
- private void setUpLoader() {
- mLoader = new DocumentLoader(
- new MtpDeviceRecord(
- 0, "Device", "Key", true, new MtpRoot[0],
- TestUtil.OPERATIONS_SUPPORTED, new int[0]),
- mManager,
- mResolver,
- mDatabase);
- }
-
- private void setUpDocument(TestMtpManager manager, int count) {
- int[] childDocuments = new int[count];
- for (int i = 0; i < childDocuments.length; i++) {
- final int objectHandle = i + 1;
- childDocuments[i] = objectHandle;
- manager.setObjectInfo(0, new MtpObjectInfo.Builder()
- .setObjectHandle(objectHandle)
- .setName(Integer.toString(i))
- .build());
- }
- manager.setObjectHandles(0, 0, MtpManager.OBJECT_HANDLE_ROOT_CHILDREN, childDocuments);
- }
-
- private static class BlockableTestMtpManager extends TestMtpManager {
- final private Map<String, CountDownLatch> blockedDocuments = new HashMap<>();
-
- BlockableTestMtpManager(Context context) {
- super(context);
- }
-
- void blockDocument(int deviceId, int objectHandle) {
- blockedDocuments.put(pack(deviceId, objectHandle), new CountDownLatch(1));
- }
-
- void unblockDocument(int deviceId, int objectHandle) {
- blockedDocuments.get(pack(deviceId, objectHandle)).countDown();
- }
-
- @Override
- MtpObjectInfo getObjectInfo(int deviceId, int objectHandle) throws IOException {
- final CountDownLatch latch = blockedDocuments.get(pack(deviceId, objectHandle));
- if (latch != null) {
- try {
- latch.await();
- } catch(InterruptedException e) {
- fail();
- }
- }
- return super.getObjectInfo(deviceId, objectHandle);
- }
- }
-}
diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDatabaseTest.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDatabaseTest.java
deleted file mode 100644
index 32b169e..0000000
--- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDatabaseTest.java
+++ /dev/null
@@ -1,1133 +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.mtp;
-
-import android.database.Cursor;
-import android.media.MediaFile;
-import android.media.MediaFile.MediaFileType;
-import android.mtp.MtpConstants;
-import android.mtp.MtpObjectInfo;
-import android.net.Uri;
-import android.provider.DocumentsContract;
-import android.provider.DocumentsContract.Document;
-import android.provider.DocumentsContract.Root;
-import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
-
-import java.io.FileNotFoundException;
-import java.util.Arrays;
-
-import static android.provider.DocumentsContract.Document.*;
-import static com.android.mtp.MtpDatabase.strings;
-import static com.android.mtp.MtpDatabaseConstants.*;
-import static com.android.mtp.TestUtil.OPERATIONS_SUPPORTED;
-
-@SmallTest
-public class MtpDatabaseTest extends AndroidTestCase {
- private static final String[] COLUMN_NAMES = new String[] {
- DocumentsContract.Document.COLUMN_DOCUMENT_ID,
- MtpDatabaseConstants.COLUMN_DEVICE_ID,
- MtpDatabaseConstants.COLUMN_STORAGE_ID,
- MtpDatabaseConstants.COLUMN_OBJECT_HANDLE,
- DocumentsContract.Document.COLUMN_MIME_TYPE,
- DocumentsContract.Document.COLUMN_DISPLAY_NAME,
- DocumentsContract.Document.COLUMN_SUMMARY,
- DocumentsContract.Document.COLUMN_LAST_MODIFIED,
- DocumentsContract.Document.COLUMN_ICON,
- DocumentsContract.Document.COLUMN_FLAGS,
- DocumentsContract.Document.COLUMN_SIZE,
- MtpDatabaseConstants.COLUMN_DOCUMENT_TYPE
- };
-
- private final TestResources resources = new TestResources();
- MtpDatabase mDatabase;
-
- @Override
- public void setUp() {
- mDatabase = new MtpDatabase(getContext(), MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
- }
-
- @Override
- public void tearDown() {
- mDatabase.close();
- mDatabase = null;
- }
-
- private static int getInt(Cursor cursor, String columnName) {
- return cursor.getInt(cursor.getColumnIndex(columnName));
- }
-
- private static boolean isNull(Cursor cursor, String columnName) {
- return cursor.isNull(cursor.getColumnIndex(columnName));
- }
-
- private static String getString(Cursor cursor, String columnName) {
- return cursor.getString(cursor.getColumnIndex(columnName));
- }
-
- public void testPutSingleStorageDocuments() throws Exception {
- addTestDevice();
-
- mDatabase.getMapper().startAddingDocuments("1");
- mDatabase.getMapper().putStorageDocuments("1", OPERATIONS_SUPPORTED, new MtpRoot[] {
- new MtpRoot(0, 1, "Storage", 1000, 2000, "")
- });
- mDatabase.getMapper().stopAddingDocuments("1");
-
- {
- final Cursor cursor = mDatabase.queryRootDocuments(COLUMN_NAMES);
- assertEquals(1, cursor.getCount());
-
- cursor.moveToNext();
- assertEquals(2, getInt(cursor, COLUMN_DOCUMENT_ID));
- assertEquals(0, getInt(cursor, COLUMN_DEVICE_ID));
- assertEquals(1, getInt(cursor, COLUMN_STORAGE_ID));
- assertTrue(isNull(cursor, COLUMN_OBJECT_HANDLE));
- assertEquals(
- DocumentsContract.Document.MIME_TYPE_DIR, getString(cursor, COLUMN_MIME_TYPE));
- assertEquals("Storage", getString(cursor, COLUMN_DISPLAY_NAME));
- assertTrue(isNull(cursor, COLUMN_SUMMARY));
- assertTrue(isNull(cursor, COLUMN_LAST_MODIFIED));
- assertEquals(R.drawable.ic_root_mtp, getInt(cursor, COLUMN_ICON));
- assertEquals(Document.FLAG_DIR_SUPPORTS_CREATE, getInt(cursor, COLUMN_FLAGS));
- assertEquals(1000, getInt(cursor, COLUMN_SIZE));
- assertEquals(
- MtpDatabaseConstants.DOCUMENT_TYPE_STORAGE,
- getInt(cursor, COLUMN_DOCUMENT_TYPE));
-
- cursor.close();
- }
-
- {
- final Cursor cursor = mDatabase.queryRoots(resources, new String [] {
- Root.COLUMN_ROOT_ID,
- Root.COLUMN_FLAGS,
- Root.COLUMN_ICON,
- Root.COLUMN_TITLE,
- Root.COLUMN_SUMMARY,
- Root.COLUMN_DOCUMENT_ID,
- Root.COLUMN_AVAILABLE_BYTES,
- Root.COLUMN_CAPACITY_BYTES
- });
- assertEquals(1, cursor.getCount());
-
- cursor.moveToNext();
- assertEquals(1, getInt(cursor, Root.COLUMN_ROOT_ID));
- assertEquals(
- Root.FLAG_SUPPORTS_IS_CHILD | Root.FLAG_SUPPORTS_CREATE | Root.FLAG_LOCAL_ONLY,
- getInt(cursor, Root.COLUMN_FLAGS));
- assertEquals(R.drawable.ic_root_mtp, getInt(cursor, Root.COLUMN_ICON));
- assertEquals("Device Storage", getString(cursor, Root.COLUMN_TITLE));
- assertTrue(isNull(cursor, Root.COLUMN_SUMMARY));
- assertEquals(1, getInt(cursor, Root.COLUMN_DOCUMENT_ID));
- assertEquals(1000, getInt(cursor, Root.COLUMN_AVAILABLE_BYTES));
- assertEquals(2000, getInt(cursor, Root.COLUMN_CAPACITY_BYTES));
-
- cursor.close();
- }
- }
-
- public void testPutStorageDocuments() throws Exception {
- addTestDevice();
-
- mDatabase.getMapper().startAddingDocuments("1");
- mDatabase.getMapper().putStorageDocuments("1", OPERATIONS_SUPPORTED, new MtpRoot[] {
- new MtpRoot(0, 1, "Storage", 1000, 2000, ""),
- new MtpRoot(0, 2, "Storage", 2000, 4000, ""),
- new MtpRoot(0, 3, "/@#%&<>Storage", 3000, 6000,"")
- });
-
- {
- final Cursor cursor = mDatabase.queryRootDocuments(COLUMN_NAMES);
- assertEquals(3, cursor.getCount());
-
- cursor.moveToNext();
- assertEquals(2, getInt(cursor, COLUMN_DOCUMENT_ID));
- assertEquals(0, getInt(cursor, COLUMN_DEVICE_ID));
- assertEquals(1, getInt(cursor, COLUMN_STORAGE_ID));
- assertTrue(isNull(cursor, COLUMN_OBJECT_HANDLE));
- assertEquals(DocumentsContract.Document.MIME_TYPE_DIR, getString(cursor, COLUMN_MIME_TYPE));
- assertEquals("Storage", getString(cursor, COLUMN_DISPLAY_NAME));
- assertTrue(isNull(cursor, COLUMN_SUMMARY));
- assertTrue(isNull(cursor, COLUMN_LAST_MODIFIED));
- assertEquals(R.drawable.ic_root_mtp, getInt(cursor, COLUMN_ICON));
- assertEquals(Document.FLAG_DIR_SUPPORTS_CREATE, getInt(cursor, COLUMN_FLAGS));
- assertEquals(1000, getInt(cursor, COLUMN_SIZE));
- assertEquals(
- MtpDatabaseConstants.DOCUMENT_TYPE_STORAGE, getInt(cursor, COLUMN_DOCUMENT_TYPE));
-
- cursor.moveToNext();
- assertEquals(3, getInt(cursor, COLUMN_DOCUMENT_ID));
- assertEquals("Storage", getString(cursor, COLUMN_DISPLAY_NAME));
-
- cursor.moveToNext();
- assertEquals(4, getInt(cursor, COLUMN_DOCUMENT_ID));
- assertEquals("/@#%&<>Storage", getString(cursor, COLUMN_DISPLAY_NAME));
-
- cursor.close();
- }
- }
-
- private MtpObjectInfo createDocument(int objectHandle, String name, int format, int size) {
- final MtpObjectInfo.Builder builder = new MtpObjectInfo.Builder();
- builder.setObjectHandle(objectHandle);
- builder.setName(name);
- builder.setFormat(format);
- builder.setCompressedSize(size);
- return builder.build();
- }
-
- public void testPutChildDocuments() throws Exception {
- addTestDevice();
- addTestStorage("1");
-
- mDatabase.getMapper().startAddingDocuments("2");
- mDatabase.getMapper().putChildDocuments(0, "2", OPERATIONS_SUPPORTED, new MtpObjectInfo[] {
- createDocument(100, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
- createDocument(101, "image.jpg", MtpConstants.FORMAT_EXIF_JPEG, 2 * 1024 * 1024),
- createDocument(102, "music.mp3", MtpConstants.FORMAT_MP3, 3 * 1024 * 1024)
- }, new long[] { 1024L, 2L * 1024L * 1024L, 3L * 1024L * 1024L});
-
- final Cursor cursor = mDatabase.queryChildDocuments(COLUMN_NAMES, "2");
- assertEquals(3, cursor.getCount());
-
- cursor.moveToNext();
- assertEquals(3, getInt(cursor, COLUMN_DOCUMENT_ID));
- assertEquals(0, getInt(cursor, COLUMN_DEVICE_ID));
- assertEquals(0, getInt(cursor, COLUMN_STORAGE_ID));
- assertEquals(100, getInt(cursor, COLUMN_OBJECT_HANDLE));
- assertEquals("text/plain", getString(cursor, COLUMN_MIME_TYPE));
- assertEquals("note.txt", getString(cursor, COLUMN_DISPLAY_NAME));
- assertTrue(isNull(cursor, COLUMN_SUMMARY));
- assertTrue(isNull(cursor, COLUMN_LAST_MODIFIED));
- assertTrue(isNull(cursor, COLUMN_ICON));
- assertEquals(
- COLUMN_FLAGS,
- DocumentsContract.Document.FLAG_SUPPORTS_DELETE |
- DocumentsContract.Document.FLAG_SUPPORTS_WRITE,
- cursor.getInt(9));
- assertEquals(1024, getInt(cursor, COLUMN_SIZE));
- assertEquals(
- MtpDatabaseConstants.DOCUMENT_TYPE_OBJECT, getInt(cursor, COLUMN_DOCUMENT_TYPE));
-
- cursor.moveToNext();
- assertEquals(4, getInt(cursor, COLUMN_DOCUMENT_ID));
- assertEquals(0, getInt(cursor, COLUMN_DEVICE_ID));
- assertEquals(0, getInt(cursor, COLUMN_STORAGE_ID));
- assertEquals(101, getInt(cursor, COLUMN_OBJECT_HANDLE));
- assertEquals("image/jpeg", getString(cursor, COLUMN_MIME_TYPE));
- assertEquals("image.jpg", getString(cursor, COLUMN_DISPLAY_NAME));
- assertTrue(isNull(cursor, COLUMN_SUMMARY));
- assertTrue(isNull(cursor, COLUMN_LAST_MODIFIED));
- assertTrue(isNull(cursor, COLUMN_ICON));
- assertEquals(
- COLUMN_FLAGS,
- DocumentsContract.Document.FLAG_SUPPORTS_DELETE |
- DocumentsContract.Document.FLAG_SUPPORTS_WRITE |
- DocumentsContract.Document.FLAG_SUPPORTS_METADATA,
- cursor.getInt(9));
- assertEquals(2 * 1024 * 1024, getInt(cursor, COLUMN_SIZE));
- assertEquals(
- MtpDatabaseConstants.DOCUMENT_TYPE_OBJECT, getInt(cursor, COLUMN_DOCUMENT_TYPE));
-
- cursor.moveToNext();
- assertEquals(5, getInt(cursor, COLUMN_DOCUMENT_ID));
- assertEquals(0, getInt(cursor, COLUMN_DEVICE_ID));
- assertEquals(0, getInt(cursor, COLUMN_STORAGE_ID));
- assertEquals(102, getInt(cursor, COLUMN_OBJECT_HANDLE));
- assertEquals("audio/mpeg", getString(cursor, COLUMN_MIME_TYPE));
- assertEquals("music.mp3", getString(cursor, COLUMN_DISPLAY_NAME));
- assertTrue(isNull(cursor, COLUMN_SUMMARY));
- assertTrue(isNull(cursor, COLUMN_LAST_MODIFIED));
- assertTrue(isNull(cursor, COLUMN_ICON));
- assertEquals(
- COLUMN_FLAGS,
- DocumentsContract.Document.FLAG_SUPPORTS_DELETE |
- DocumentsContract.Document.FLAG_SUPPORTS_WRITE,
- cursor.getInt(9));
- assertEquals(3 * 1024 * 1024, getInt(cursor, COLUMN_SIZE));
- assertEquals(
- MtpDatabaseConstants.DOCUMENT_TYPE_OBJECT, getInt(cursor, COLUMN_DOCUMENT_TYPE));
-
- cursor.close();
- }
-
- public void testPutChildDocuments_operationsSupported() throws Exception {
- addTestDevice();
- addTestStorage("1");
-
- // Put a document with empty supported operations.
- mDatabase.getMapper().startAddingDocuments("2");
- mDatabase.getMapper().putChildDocuments(0, "2", new int[0], new MtpObjectInfo[] {
- createDocument(100, "note.txt", MtpConstants.FORMAT_TEXT, 1024)
- }, new long[] { 1024L });
- mDatabase.getMapper().stopAddingDocuments("2");
-
- try (final Cursor cursor =
- mDatabase.queryChildDocuments(strings(Document.COLUMN_FLAGS), "2")) {
- assertEquals(1, cursor.getCount());
- cursor.moveToNext();
- assertEquals(0, cursor.getInt(0));
- }
-
- // Put a document with writable operations.
- mDatabase.getMapper().startAddingDocuments("2");
- mDatabase.getMapper().putChildDocuments(0, "2", new int[] {
- MtpConstants.OPERATION_SEND_OBJECT,
- MtpConstants.OPERATION_SEND_OBJECT_INFO,
- }, new MtpObjectInfo[] {
- createDocument(100, "note.txt", MtpConstants.FORMAT_TEXT, 1024)
- }, new long[] { 1024L });
- mDatabase.getMapper().stopAddingDocuments("2");
-
- try (final Cursor cursor =
- mDatabase.queryChildDocuments(strings(Document.COLUMN_FLAGS), "2")) {
- assertEquals(1, cursor.getCount());
- cursor.moveToNext();
- assertEquals(Document.FLAG_SUPPORTS_WRITE, cursor.getInt(0));
- }
-
- // Put a document with deletable operations.
- mDatabase.getMapper().startAddingDocuments("2");
- mDatabase.getMapper().putChildDocuments(0, "2", new int[] {
- MtpConstants.OPERATION_DELETE_OBJECT
- }, new MtpObjectInfo[] {
- createDocument(100, "note.txt", MtpConstants.FORMAT_TEXT, 1024)
- }, new long[] { 1024L });
- mDatabase.getMapper().stopAddingDocuments("2");
-
- try (final Cursor cursor =
- mDatabase.queryChildDocuments(strings(Document.COLUMN_FLAGS), "2")) {
- assertEquals(1, cursor.getCount());
- cursor.moveToNext();
- assertEquals(Document.FLAG_SUPPORTS_DELETE, cursor.getInt(0));
- }
- }
-
- public void testRestoreIdForRootDocuments() throws Exception {
- final String[] columns = new String[] {
- DocumentsContract.Document.COLUMN_DOCUMENT_ID,
- MtpDatabaseConstants.COLUMN_STORAGE_ID,
- DocumentsContract.Document.COLUMN_DISPLAY_NAME
- };
-
- // Add device and two storages.
- addTestDevice();
- mDatabase.getMapper().startAddingDocuments("1");
- mDatabase.getMapper().putStorageDocuments("1", OPERATIONS_SUPPORTED, new MtpRoot[] {
- new MtpRoot(0, 100, "Storage A", 1000, 0, ""),
- new MtpRoot(0, 101, "Storage B", 1001, 0, "")
- });
-
- {
- final Cursor cursor = mDatabase.queryRootDocuments(columns);
- assertEquals(2, cursor.getCount());
- cursor.moveToNext();
- assertEquals(2, getInt(cursor, COLUMN_DOCUMENT_ID));
- assertEquals(100, getInt(cursor, COLUMN_STORAGE_ID));
- assertEquals("Storage A", getString(cursor, COLUMN_DISPLAY_NAME));
- cursor.moveToNext();
- assertEquals(3, getInt(cursor, COLUMN_DOCUMENT_ID));
- assertEquals(101, getInt(cursor, COLUMN_STORAGE_ID));
- assertEquals("Storage B", getString(cursor, COLUMN_DISPLAY_NAME));
- cursor.close();
- }
-
- // Clear mapping and add a device.
- mDatabase.getMapper().clearMapping();
- addTestDevice();
-
- {
- final Cursor cursor = mDatabase.queryRootDocuments(columns);
- assertEquals(0, cursor.getCount());
- cursor.close();
- }
-
- // Add two storages, but one's name is different from previous one.
- mDatabase.getMapper().startAddingDocuments("1");
- mDatabase.getMapper().putStorageDocuments("1", OPERATIONS_SUPPORTED, new MtpRoot[] {
- new MtpRoot(0, 200, "Storage A", 2000, 0, ""),
- new MtpRoot(0, 202, "Storage C", 2002, 0, "")
- });
- mDatabase.getMapper().stopAddingDocuments("1");
-
- {
- // After compeleting mapping, Storage A can be obtained with new storage ID.
- final Cursor cursor = mDatabase.queryRootDocuments(columns);
- assertEquals(2, cursor.getCount());
- cursor.moveToNext();
- assertEquals(2, getInt(cursor, COLUMN_DOCUMENT_ID));
- assertEquals(200, getInt(cursor, COLUMN_STORAGE_ID));
- assertEquals("Storage A", getString(cursor, COLUMN_DISPLAY_NAME));
- cursor.moveToNext();
- assertEquals(4, getInt(cursor, COLUMN_DOCUMENT_ID));
- assertEquals(202, getInt(cursor, COLUMN_STORAGE_ID));
- assertEquals("Storage C", getString(cursor, COLUMN_DISPLAY_NAME));
- cursor.close();
- }
- }
-
- public void testRestoreIdForChildDocuments() throws Exception {
- final String[] columns = new String[] {
- DocumentsContract.Document.COLUMN_DOCUMENT_ID,
- MtpDatabaseConstants.COLUMN_OBJECT_HANDLE,
- DocumentsContract.Document.COLUMN_DISPLAY_NAME
- };
-
- addTestDevice();
- addTestStorage("1");
-
- mDatabase.getMapper().startAddingDocuments("2");
- mDatabase.getMapper().putChildDocuments(0, "2", OPERATIONS_SUPPORTED, new MtpObjectInfo[] {
- createDocument(100, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
- createDocument(101, "image.jpg", MtpConstants.FORMAT_EXIF_JPEG, 2 * 1024 * 1024),
- createDocument(102, "music.mp3", MtpConstants.FORMAT_MP3, 3 * 1024 * 1024)
- }, new long[] { 1024L, 2L * 1024L * 1024L, 3L * 1024L * 1024L});
- mDatabase.getMapper().clearMapping();
-
- addTestDevice();
- addTestStorage("1");
-
- {
- // Don't return objects that lost MTP object handles.
- final Cursor cursor = mDatabase.queryChildDocuments(columns, "2");
- assertEquals(0, cursor.getCount());
- cursor.close();
- }
-
- mDatabase.getMapper().startAddingDocuments("2");
- mDatabase.getMapper().putChildDocuments(0, "2", OPERATIONS_SUPPORTED, new MtpObjectInfo[] {
- createDocument(200, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
- createDocument(203, "video.mp4", MtpConstants.FORMAT_MP4_CONTAINER, 1024),
- }, new long[] { 1024L, 1024L });
- mDatabase.getMapper().stopAddingDocuments("2");
-
- {
- final Cursor cursor = mDatabase.queryChildDocuments(columns, "2");
- assertEquals(2, cursor.getCount());
-
- cursor.moveToNext();
- assertEquals(3, getInt(cursor, COLUMN_DOCUMENT_ID));
- assertEquals(200, getInt(cursor, COLUMN_OBJECT_HANDLE));
- assertEquals("note.txt", getString(cursor, COLUMN_DISPLAY_NAME));
-
- cursor.moveToNext();
- assertEquals(6, getInt(cursor, COLUMN_DOCUMENT_ID));
- assertEquals(203, getInt(cursor, COLUMN_OBJECT_HANDLE));
- assertEquals("video.mp4", getString(cursor, COLUMN_DISPLAY_NAME));
-
- cursor.close();
- }
- }
-
- public void testRestoreIdForDifferentDevices() throws Exception {
- final String[] columns = new String[] {
- DocumentsContract.Document.COLUMN_DOCUMENT_ID,
- MtpDatabaseConstants.COLUMN_STORAGE_ID,
- DocumentsContract.Document.COLUMN_DISPLAY_NAME
- };
- final String[] rootColumns = new String[] {
- Root.COLUMN_ROOT_ID,
- Root.COLUMN_AVAILABLE_BYTES
- };
- mDatabase.getMapper().startAddingDocuments(null);
- mDatabase.getMapper().putDeviceDocument(new MtpDeviceRecord(
- 0, "Device A", "Device key A", true, new MtpRoot[0], null, null));
- mDatabase.getMapper().putDeviceDocument(new MtpDeviceRecord(
- 1, "Device B", "Device key B", true, new MtpRoot[0], null, null));
- mDatabase.getMapper().stopAddingDocuments(null);
-
- mDatabase.getMapper().startAddingDocuments("1");
- mDatabase.getMapper().startAddingDocuments("2");
- mDatabase.getMapper().putStorageDocuments("1", OPERATIONS_SUPPORTED, new MtpRoot[] {
- new MtpRoot(0, 100, "Storage", 0, 0, "")
- });
- mDatabase.getMapper().putStorageDocuments("2", OPERATIONS_SUPPORTED, new MtpRoot[] {
- new MtpRoot(1, 100, "Storage", 0, 0, "")
- });
-
- {
- final Cursor cursor = mDatabase.queryRootDocuments(columns);
- assertEquals(2, cursor.getCount());
- cursor.moveToNext();
- assertEquals(3, getInt(cursor, COLUMN_DOCUMENT_ID));
- assertEquals(100, getInt(cursor, COLUMN_STORAGE_ID));
- assertEquals("Storage", getString(cursor, COLUMN_DISPLAY_NAME));
- cursor.moveToNext();
- assertEquals(4, getInt(cursor, COLUMN_DOCUMENT_ID));
- assertEquals(100, getInt(cursor, COLUMN_STORAGE_ID));
- assertEquals("Storage", getString(cursor, COLUMN_DISPLAY_NAME));
- cursor.close();
- }
-
- {
- final Cursor cursor = mDatabase.queryRoots(resources, rootColumns);
- assertEquals(2, cursor.getCount());
- cursor.moveToNext();
- assertEquals(1, getInt(cursor, Root.COLUMN_ROOT_ID));
- assertEquals(0, getInt(cursor, Root.COLUMN_AVAILABLE_BYTES));
- cursor.moveToNext();
- assertEquals(2, getInt(cursor, Root.COLUMN_ROOT_ID));
- assertEquals(0, getInt(cursor, Root.COLUMN_AVAILABLE_BYTES));
- cursor.close();
- }
-
- mDatabase.getMapper().clearMapping();
-
- mDatabase.getMapper().startAddingDocuments(null);
- mDatabase.getMapper().putDeviceDocument(new MtpDeviceRecord(
- 0, "Device A", "Device key A", true, new MtpRoot[0], null, null));
- mDatabase.getMapper().putDeviceDocument(new MtpDeviceRecord(
- 1, "Device B", "Device key B", true, new MtpRoot[0], null, null));
- mDatabase.getMapper().stopAddingDocuments(null);
-
- mDatabase.getMapper().startAddingDocuments("1");
- mDatabase.getMapper().startAddingDocuments("2");
- mDatabase.getMapper().putStorageDocuments("1", OPERATIONS_SUPPORTED, new MtpRoot[] {
- new MtpRoot(0, 200, "Storage", 2000, 0, "")
- });
- mDatabase.getMapper().putStorageDocuments("2", OPERATIONS_SUPPORTED, new MtpRoot[] {
- new MtpRoot(1, 300, "Storage", 3000, 0, "")
- });
- mDatabase.getMapper().stopAddingDocuments("1");
- mDatabase.getMapper().stopAddingDocuments("2");
-
- {
- final Cursor cursor = mDatabase.queryRootDocuments(columns);
- assertEquals(2, cursor.getCount());
- cursor.moveToNext();
- assertEquals(3, getInt(cursor, COLUMN_DOCUMENT_ID));
- assertEquals(200, getInt(cursor, COLUMN_STORAGE_ID));
- assertEquals("Storage", getString(cursor, COLUMN_DISPLAY_NAME));
- cursor.moveToNext();
- assertEquals(4, getInt(cursor, COLUMN_DOCUMENT_ID));
- assertEquals(300, getInt(cursor, COLUMN_STORAGE_ID));
- assertEquals("Storage", getString(cursor, COLUMN_DISPLAY_NAME));
- cursor.close();
- }
-
- {
- final Cursor cursor = mDatabase.queryRoots(resources, rootColumns);
- assertEquals(2, cursor.getCount());
- cursor.moveToNext();
- assertEquals(1, getInt(cursor, Root.COLUMN_ROOT_ID));
- assertEquals(2000, getInt(cursor, Root.COLUMN_AVAILABLE_BYTES));
- cursor.moveToNext();
- assertEquals(2, getInt(cursor, Root.COLUMN_ROOT_ID));
- assertEquals(3000, getInt(cursor, Root.COLUMN_AVAILABLE_BYTES));
- cursor.close();
- }
- }
-
- public void testRestoreIdForDifferentParents() throws Exception {
- final String[] columns = new String[] {
- DocumentsContract.Document.COLUMN_DOCUMENT_ID,
- MtpDatabaseConstants.COLUMN_OBJECT_HANDLE
- };
-
- // Add device, storage, and two directories.
- addTestDevice();
- addTestStorage("1");
- mDatabase.getMapper().startAddingDocuments("2");
- mDatabase.getMapper().putChildDocuments(0, "2", OPERATIONS_SUPPORTED, new MtpObjectInfo[] {
- createDocument(50, "A", MtpConstants.FORMAT_ASSOCIATION, 0),
- createDocument(51, "B", MtpConstants.FORMAT_ASSOCIATION, 0),
- }, new long[] { 0L, 0L });
- mDatabase.getMapper().stopAddingDocuments("2");
-
- // Put note.txt in each directory.
- mDatabase.getMapper().startAddingDocuments("3");
- mDatabase.getMapper().startAddingDocuments("4");
- mDatabase.getMapper().putChildDocuments(0, "3", OPERATIONS_SUPPORTED, new MtpObjectInfo[] {
- createDocument(100, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
- }, new long[] { 1024L });
- mDatabase.getMapper().putChildDocuments(0, "4", OPERATIONS_SUPPORTED, new MtpObjectInfo[] {
- createDocument(101, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
- }, new long[] { 1024L });
-
- // Clear mapping.
- mDatabase.getMapper().clearMapping();
-
- // Add device, storage, and two directories again.
- addTestDevice();
- addTestStorage("1");
- mDatabase.getMapper().startAddingDocuments("2");
- mDatabase.getMapper().putChildDocuments(0, "2", OPERATIONS_SUPPORTED, new MtpObjectInfo[] {
- createDocument(50, "A", MtpConstants.FORMAT_ASSOCIATION, 0),
- createDocument(51, "B", MtpConstants.FORMAT_ASSOCIATION, 0),
- }, new long[] { 0L, 0L });
- mDatabase.getMapper().stopAddingDocuments("2");
-
- // Add note.txt in each directory again.
- mDatabase.getMapper().startAddingDocuments("3");
- mDatabase.getMapper().startAddingDocuments("4");
- mDatabase.getMapper().putChildDocuments(0, "3", OPERATIONS_SUPPORTED, new MtpObjectInfo[] {
- createDocument(200, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
- }, new long[] { 1024L });
- mDatabase.getMapper().putChildDocuments(0, "4", OPERATIONS_SUPPORTED, new MtpObjectInfo[] {
- createDocument(201, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
- }, new long[] { 1024L });
- mDatabase.getMapper().stopAddingDocuments("3");
- mDatabase.getMapper().stopAddingDocuments("4");
-
- // Check if the two note.txt are mapped correctly.
- {
- final Cursor cursor = mDatabase.queryChildDocuments(columns, "3");
- assertEquals(1, cursor.getCount());
- cursor.moveToNext();
- assertEquals(5, getInt(cursor, COLUMN_DOCUMENT_ID));
- assertEquals(200, getInt(cursor, COLUMN_OBJECT_HANDLE));
- cursor.close();
- }
- {
- final Cursor cursor = mDatabase.queryChildDocuments(columns, "4");
- assertEquals(1, cursor.getCount());
- cursor.moveToNext();
- assertEquals(6, getInt(cursor, COLUMN_DOCUMENT_ID));
- assertEquals(201, getInt(cursor, COLUMN_OBJECT_HANDLE));
- cursor.close();
- }
- }
-
- public void testClearMtpIdentifierBeforeResolveRootDocuments() throws Exception {
- final String[] columns = new String[] {
- DocumentsContract.Document.COLUMN_DOCUMENT_ID,
- MtpDatabaseConstants.COLUMN_STORAGE_ID,
- DocumentsContract.Document.COLUMN_DISPLAY_NAME
- };
- final String[] rootColumns = new String[] {
- Root.COLUMN_ROOT_ID,
- Root.COLUMN_AVAILABLE_BYTES
- };
-
- addTestDevice();
-
- mDatabase.getMapper().startAddingDocuments("1");
- mDatabase.getMapper().putStorageDocuments("1", OPERATIONS_SUPPORTED, new MtpRoot[] {
- new MtpRoot(0, 100, "Storage", 0, 0, ""),
- });
- mDatabase.getMapper().clearMapping();
-
- addTestDevice();
-
- try (final Cursor cursor = mDatabase.queryRoots(resources, rootColumns)) {
- assertEquals(1, cursor.getCount());
- cursor.moveToNext();
- assertEquals("1", getString(cursor, Root.COLUMN_ROOT_ID));
- }
-
- mDatabase.getMapper().startAddingDocuments("1");
- mDatabase.getMapper().putStorageDocuments("1", OPERATIONS_SUPPORTED, new MtpRoot[] {
- new MtpRoot(0, 200, "Storage", 2000, 0, ""),
- });
- mDatabase.getMapper().clearMapping();
-
- addTestDevice();
-
- mDatabase.getMapper().startAddingDocuments("1");
- mDatabase.getMapper().putStorageDocuments("1", OPERATIONS_SUPPORTED, new MtpRoot[] {
- new MtpRoot(0, 300, "Storage", 3000, 0, ""),
- });
- mDatabase.getMapper().stopAddingDocuments("1");
-
- {
- final Cursor cursor = mDatabase.queryRootDocuments(columns);
- assertEquals(1, cursor.getCount());
- cursor.moveToNext();
- assertEquals(2, getInt(cursor, COLUMN_DOCUMENT_ID));
- assertEquals(300, getInt(cursor, COLUMN_STORAGE_ID));
- assertEquals("Storage", getString(cursor, COLUMN_DISPLAY_NAME));
- cursor.close();
- }
- {
- final Cursor cursor = mDatabase.queryRoots(resources, rootColumns);
- assertEquals(1, cursor.getCount());
- cursor.moveToNext();
- assertEquals(1, getInt(cursor, Root.COLUMN_ROOT_ID));
- assertEquals(3000, getInt(cursor, Root.COLUMN_AVAILABLE_BYTES));
- cursor.close();
- }
- }
-
- public void testPutSameNameRootsAfterClearing() throws Exception {
- final String[] columns = new String[] {
- DocumentsContract.Document.COLUMN_DOCUMENT_ID,
- MtpDatabaseConstants.COLUMN_STORAGE_ID,
- DocumentsContract.Document.COLUMN_DISPLAY_NAME
- };
-
- // Add a device and a storage.
- addTestDevice();
- addTestStorage("1");
-
- // Disconnect devices.
- mDatabase.getMapper().clearMapping();
-
- // Add a device and two storages that has same name.
- addTestDevice();
- mDatabase.getMapper().startAddingDocuments("1");
- mDatabase.getMapper().putStorageDocuments("1", OPERATIONS_SUPPORTED, new MtpRoot[] {
- new MtpRoot(0, 200, "Storage", 2000, 0, ""),
- new MtpRoot(0, 201, "Storage", 2001, 0, ""),
- });
- mDatabase.getMapper().stopAddingDocuments("1");
-
- {
- final Cursor cursor = mDatabase.queryRootDocuments(columns);
- assertEquals(2, cursor.getCount());
-
- // First storage reuse document ID of previous storage.
- cursor.moveToNext();
- // One reuses exisitng document ID 1.
- assertEquals(2, getInt(cursor, COLUMN_DOCUMENT_ID));
- assertEquals(200, getInt(cursor, COLUMN_STORAGE_ID));
- assertEquals("Storage", getString(cursor, COLUMN_DISPLAY_NAME));
-
- // Second one has new document ID.
- cursor.moveToNext();
- assertEquals(3, getInt(cursor, COLUMN_DOCUMENT_ID));
- assertEquals(201, getInt(cursor, COLUMN_STORAGE_ID));
- assertEquals("Storage", getString(cursor, COLUMN_DISPLAY_NAME));
-
- cursor.close();
- }
- }
-
- public void testReplaceExistingRoots() throws Exception {
- addTestDevice();
-
- // The client code should be able to replace existing rows with new information.
- // Add one.
- mDatabase.getMapper().startAddingDocuments("1");
- mDatabase.getMapper().putStorageDocuments("1", OPERATIONS_SUPPORTED, new MtpRoot[] {
- new MtpRoot(0, 100, "Storage A", 0, 0, ""),
- });
- mDatabase.getMapper().stopAddingDocuments("1");
- // Replace it.
- mDatabase.getMapper().startAddingDocuments("1");
- mDatabase.getMapper().putStorageDocuments("1", OPERATIONS_SUPPORTED, new MtpRoot[] {
- new MtpRoot(0, 100, "Storage B", 1000, 1000, ""),
- });
- mDatabase.getMapper().stopAddingDocuments("1");
- {
- final String[] columns = new String[] {
- DocumentsContract.Document.COLUMN_DOCUMENT_ID,
- MtpDatabaseConstants.COLUMN_STORAGE_ID,
- DocumentsContract.Document.COLUMN_DISPLAY_NAME
- };
- final Cursor cursor = mDatabase.queryRootDocuments(columns);
- assertEquals(1, cursor.getCount());
- cursor.moveToNext();
- assertEquals(2, getInt(cursor, COLUMN_DOCUMENT_ID));
- assertEquals(100, getInt(cursor, COLUMN_STORAGE_ID));
- assertEquals("Storage B", getString(cursor, COLUMN_DISPLAY_NAME));
- cursor.close();
- }
- {
- final String[] columns = new String[] {
- Root.COLUMN_ROOT_ID,
- Root.COLUMN_TITLE,
- Root.COLUMN_AVAILABLE_BYTES
- };
- final Cursor cursor = mDatabase.queryRoots(resources, columns);
- assertEquals(1, cursor.getCount());
- cursor.moveToNext();
- assertEquals(1, getInt(cursor, Root.COLUMN_ROOT_ID));
- assertEquals("Device Storage B", getString(cursor, Root.COLUMN_TITLE));
- assertEquals(1000, getInt(cursor, Root.COLUMN_AVAILABLE_BYTES));
- cursor.close();
- }
- }
-
- public void testFailToReplaceExisitingUnmappedRoots() throws Exception {
- // The client code should not be able to replace rows before resolving 'unmapped' rows.
- // Add one.
- addTestDevice();
- mDatabase.getMapper().startAddingDocuments("1");
- mDatabase.getMapper().putStorageDocuments("1", OPERATIONS_SUPPORTED, new MtpRoot[] {
- new MtpRoot(0, 100, "Storage A", 0, 0, ""),
- });
- mDatabase.getMapper().clearMapping();
-
- addTestDevice();
- try (final Cursor oldCursor =
- mDatabase.queryRoots(resources, strings(Root.COLUMN_ROOT_ID))) {
- assertEquals(1, oldCursor.getCount());
- oldCursor.moveToNext();
- assertEquals("1", getString(oldCursor, Root.COLUMN_ROOT_ID));
-
- // Add one.
- mDatabase.getMapper().startAddingDocuments("1");
- mDatabase.getMapper().putStorageDocuments("1", OPERATIONS_SUPPORTED, new MtpRoot[] {
- new MtpRoot(0, 101, "Storage B", 1000, 1000, ""),
- });
- // Add one more before resolving unmapped documents.
- mDatabase.getMapper().putStorageDocuments("1", OPERATIONS_SUPPORTED, new MtpRoot[] {
- new MtpRoot(0, 102, "Storage B", 1000, 1000, ""),
- });
- mDatabase.getMapper().stopAddingDocuments("1");
-
- // Because the roots shares the same name, the roots should have new IDs.
- try (final Cursor newCursor = mDatabase.queryChildDocuments(
- strings(Document.COLUMN_DOCUMENT_ID), "1")) {
- assertEquals(2, newCursor.getCount());
- newCursor.moveToNext();
- assertFalse(oldCursor.getString(0).equals(newCursor.getString(0)));
- newCursor.moveToNext();
- assertFalse(oldCursor.getString(0).equals(newCursor.getString(0)));
- }
- }
- }
-
- public void testQueryDocuments() throws Exception {
- addTestDevice();
- addTestStorage("1");
-
- final Cursor cursor = mDatabase.queryDocument("2", strings(Document.COLUMN_DISPLAY_NAME));
- assertEquals(1, cursor.getCount());
- cursor.moveToNext();
- assertEquals("Storage", getString(cursor, Document.COLUMN_DISPLAY_NAME));
- cursor.close();
- }
-
- public void testQueryRoots() throws Exception {
- // Add device document.
- addTestDevice();
-
- // It the device does not have storages, it shows a device root.
- {
- final Cursor cursor = mDatabase.queryRoots(resources, strings(Root.COLUMN_TITLE));
- assertEquals(1, cursor.getCount());
- cursor.moveToNext();
- assertEquals("Device", cursor.getString(0));
- cursor.close();
- }
-
- mDatabase.getMapper().startAddingDocuments("1");
- mDatabase.getMapper().putStorageDocuments("1", OPERATIONS_SUPPORTED, new MtpRoot[] {
- new MtpRoot(0, 100, "Storage A", 0, 0, "")
- });
- mDatabase.getMapper().stopAddingDocuments("1");
-
- // It the device has single storage, it shows a storage root.
- {
- final Cursor cursor = mDatabase.queryRoots(resources, strings(Root.COLUMN_TITLE));
- assertEquals(1, cursor.getCount());
- cursor.moveToNext();
- assertEquals("Device Storage A", cursor.getString(0));
- cursor.close();
- }
-
- mDatabase.getMapper().startAddingDocuments("1");
- mDatabase.getMapper().putStorageDocuments("1", OPERATIONS_SUPPORTED, new MtpRoot[] {
- new MtpRoot(0, 100, "Storage A", 0, 0, ""),
- new MtpRoot(0, 101, "Storage B", 0, 0, "")
- });
- mDatabase.getMapper().stopAddingDocuments("1");
-
- // It the device has multiple storages, it shows a device root.
- {
- final Cursor cursor = mDatabase.queryRoots(resources, strings(Root.COLUMN_TITLE));
- assertEquals(1, cursor.getCount());
- cursor.moveToNext();
- assertEquals("Device", cursor.getString(0));
- cursor.close();
- }
- }
-
- public void testGetParentId() throws FileNotFoundException {
- addTestDevice();
-
- mDatabase.getMapper().startAddingDocuments("1");
- mDatabase.getMapper().putStorageDocuments("1", OPERATIONS_SUPPORTED, new MtpRoot[] {
- new MtpRoot(0, 100, "Storage A", 0, 0, ""),
- });
- mDatabase.getMapper().stopAddingDocuments("1");
-
- mDatabase.getMapper().startAddingDocuments("2");
- mDatabase.getMapper().putChildDocuments(0, "2", OPERATIONS_SUPPORTED, new MtpObjectInfo[] {
- createDocument(200, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
- }, new long[] { 1024L });
- mDatabase.getMapper().stopAddingDocuments("2");
-
- assertEquals("2", mDatabase.getParentIdentifier("3").mDocumentId);
- }
-
- public void testDeleteDocument() throws Exception {
- addTestDevice();
- addTestStorage("1");
-
- mDatabase.getMapper().startAddingDocuments("2");
- mDatabase.getMapper().putChildDocuments(0, "2", OPERATIONS_SUPPORTED, new MtpObjectInfo[] {
- createDocument(200, "dir", MtpConstants.FORMAT_ASSOCIATION, 1024),
- }, new long[] { 1024L });
- mDatabase.getMapper().stopAddingDocuments("2");
-
- mDatabase.getMapper().startAddingDocuments("3");
- mDatabase.getMapper().putChildDocuments(0, "3", OPERATIONS_SUPPORTED, new MtpObjectInfo[] {
- createDocument(200, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
- }, new long[] { 1024L });
- mDatabase.getMapper().stopAddingDocuments("3");
-
- mDatabase.deleteDocument("3");
-
- {
- // Do not query deleted documents.
- final Cursor cursor =
- mDatabase.queryChildDocuments(strings(Document.COLUMN_DOCUMENT_ID), "2");
- assertEquals(0, cursor.getCount());
- cursor.close();
- }
-
- {
- // Child document should be deleted also.
- final Cursor cursor =
- mDatabase.queryDocument("4", strings(Document.COLUMN_DOCUMENT_ID));
- assertEquals(0, cursor.getCount());
- cursor.close();
- }
- }
-
- public void testPutNewDocument() throws Exception {
- addTestDevice();
- addTestStorage("1");
-
- assertEquals(
- "3",
- mDatabase.putNewDocument(
- 0, "2", OPERATIONS_SUPPORTED,
- createDocument(200, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
- 1024L));
-
- {
- final Cursor cursor =
- mDatabase.queryChildDocuments(strings(Document.COLUMN_DOCUMENT_ID), "2");
- assertEquals(1, cursor.getCount());
- cursor.moveToNext();
- assertEquals("3", cursor.getString(0));
- cursor.close();
- }
-
- // The new document should not be mapped with existing invalidated document.
- mDatabase.getMapper().clearMapping();
- addTestDevice();
- addTestStorage("1");
-
- mDatabase.getMapper().startAddingDocuments("2");
- mDatabase.putNewDocument(
- 0, "2", OPERATIONS_SUPPORTED,
- createDocument(201, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
- 1024L);
- mDatabase.getMapper().stopAddingDocuments("2");
-
- {
- final Cursor cursor =
- mDatabase.queryChildDocuments(strings(Document.COLUMN_DOCUMENT_ID), "2");
- assertEquals(1, cursor.getCount());
- cursor.moveToNext();
- assertEquals("4", cursor.getString(0));
- cursor.close();
- }
- }
-
- public void testGetDocumentIdForDevice() throws Exception {
- addTestDevice();
- assertEquals("1", mDatabase.getDocumentIdForDevice(0));
- }
-
- public void testGetClosedDevice() throws Exception {
- mDatabase.getMapper().startAddingDocuments(null);
- mDatabase.getMapper().putDeviceDocument(new MtpDeviceRecord(
- 0, "Device", null /* deviceKey */, /* opened is */ false, new MtpRoot[0], null,
- null));
- mDatabase.getMapper().stopAddingDocuments(null);
-
- final String[] columns = new String [] {
- DocumentsContract.Root.COLUMN_ROOT_ID,
- DocumentsContract.Root.COLUMN_TITLE,
- DocumentsContract.Root.COLUMN_AVAILABLE_BYTES
- };
- try (final Cursor cursor = mDatabase.queryRoots(resources, columns)) {
- assertEquals(1, cursor.getCount());
- assertTrue(cursor.moveToNext());
- assertEquals(1, cursor.getLong(0));
- assertEquals("Device", cursor.getString(1));
- assertTrue(cursor.isNull(2));
- }
- }
-
- public void testMappingWithoutKey() throws FileNotFoundException {
- mDatabase.getMapper().startAddingDocuments(null);
- mDatabase.getMapper().putDeviceDocument(new MtpDeviceRecord(
- 0, "Device", null /* device key */, /* opened is */ true, new MtpRoot[0], null,
- null));
- mDatabase.getMapper().stopAddingDocuments(null);
-
- mDatabase.getMapper().startAddingDocuments(null);
- mDatabase.getMapper().putDeviceDocument(new MtpDeviceRecord(
- 0, "Device", null /* device key */, /* opened is */ true, new MtpRoot[0], null,
- null));
- mDatabase.getMapper().stopAddingDocuments(null);
-
- try (final Cursor cursor =
- mDatabase.queryRoots(resources, strings(DocumentsContract.Root.COLUMN_ROOT_ID))) {
- assertEquals(1, cursor.getCount());
- assertTrue(cursor.moveToNext());
- assertEquals(1, cursor.getLong(0));
- }
- }
-
- public void testMappingFailsWithoutKey() throws FileNotFoundException {
- mDatabase.getMapper().startAddingDocuments(null);
- mDatabase.getMapper().putDeviceDocument(new MtpDeviceRecord(
- 0, "Device", null /* device key */, /* opened is */ true, new MtpRoot[0], null,
- null));
- mDatabase.getMapper().stopAddingDocuments(null);
-
- // MTP identifier is cleared here. Mapping no longer works without device key.
- mDatabase.getMapper().startAddingDocuments(null);
- mDatabase.getMapper().stopAddingDocuments(null);
-
- mDatabase.getMapper().startAddingDocuments(null);
- mDatabase.getMapper().putDeviceDocument(new MtpDeviceRecord(
- 0, "Device", null /* device key */, /* opened is */ true, new MtpRoot[0], null,
- null));
- mDatabase.getMapper().stopAddingDocuments(null);
-
- try (final Cursor cursor =
- mDatabase.queryRoots(resources, strings(DocumentsContract.Root.COLUMN_ROOT_ID))) {
- assertEquals(1, cursor.getCount());
- assertTrue(cursor.moveToNext());
- assertEquals(2, cursor.getLong(0));
- }
- }
-
- public void testUpdateDocumentWithoutChange() throws FileNotFoundException {
- mDatabase.getMapper().startAddingDocuments(null);
- assertTrue(mDatabase.getMapper().putDeviceDocument(new MtpDeviceRecord(
- 0, "Device", "device_key", /* opened is */ true, new MtpRoot[0], null,
- null)));
- assertFalse(mDatabase.getMapper().stopAddingDocuments(null));
-
- mDatabase.getMapper().startAddingDocuments(null);
- assertFalse(mDatabase.getMapper().putDeviceDocument(new MtpDeviceRecord(
- 0, "Device", "device_key", /* opened is */ true, new MtpRoot[0], null,
- null)));
- assertFalse(mDatabase.getMapper().stopAddingDocuments(null));
- }
-
- public void testSetBootCount() {
- assertEquals(0, mDatabase.getLastBootCount());
- mDatabase.setLastBootCount(10);
- assertEquals(10, mDatabase.getLastBootCount());
- try {
- mDatabase.setLastBootCount(-1);
- fail();
- } catch (IllegalArgumentException e) {}
- }
-
- public void testCleanDatabase() throws FileNotFoundException {
- // Add tree.
- addTestDevice();
- addTestStorage("1");
- mDatabase.getMapper().startAddingDocuments("2");
- mDatabase.getMapper().putChildDocuments(0, "2", OPERATIONS_SUPPORTED, new MtpObjectInfo[] {
- createDocument(100, "apple.txt", MtpConstants.FORMAT_TEXT, 1024),
- createDocument(101, "orange.txt", MtpConstants.FORMAT_TEXT, 1024),
- }, new long[] { 1024L, 1024L });
- mDatabase.getMapper().stopAddingDocuments("2");
-
- // Disconnect the device.
- mDatabase.getMapper().startAddingDocuments(null);
- mDatabase.getMapper().stopAddingDocuments(null);
-
- // Clean database.
- mDatabase.cleanDatabase(new Uri[] {
- DocumentsContract.buildDocumentUri(MtpDocumentsProvider.AUTHORITY, "3")
- });
-
- // Add tree again.
- addTestDevice();
- addTestStorage("1");
- mDatabase.getMapper().startAddingDocuments("2");
- mDatabase.getMapper().putChildDocuments(0, "2", OPERATIONS_SUPPORTED, new MtpObjectInfo[] {
- createDocument(100, "apple.txt", MtpConstants.FORMAT_TEXT, 1024),
- createDocument(101, "orange.txt", MtpConstants.FORMAT_TEXT, 1024),
- }, new long[] { 1024L, 1024L });
- mDatabase.getMapper().stopAddingDocuments("2");
-
- try (final Cursor cursor = mDatabase.queryChildDocuments(
- strings(COLUMN_DOCUMENT_ID, Document.COLUMN_DISPLAY_NAME), "2")) {
- assertEquals(2, cursor.getCount());
-
- // Persistent uri uses the same ID.
- cursor.moveToNext();
- assertEquals("3", cursor.getString(0));
- assertEquals("apple.txt", cursor.getString(1));
-
- // Others does not.
- cursor.moveToNext();
- assertEquals("5", cursor.getString(0));
- assertEquals("orange.txt", cursor.getString(1));
- }
- }
-
- public void testFormatCodeForMpeg() throws FileNotFoundException {
- addTestDevice();
- addTestStorage("1");
- mDatabase.getMapper().startAddingDocuments("2");
- mDatabase.getMapper().putChildDocuments(0, "2", OPERATIONS_SUPPORTED, new MtpObjectInfo[] {
- createDocument(100, "audio.m4a", MtpConstants.FORMAT_MPEG, 1000),
- createDocument(101, "video.m4v", MtpConstants.FORMAT_MPEG, 1000),
- createDocument(102, "unknown.mp4", MtpConstants.FORMAT_MPEG, 1000),
- createDocument(103, "inconsistent.txt", MtpConstants.FORMAT_MPEG, 1000),
- createDocument(104, "noext", MtpConstants.FORMAT_UNDEFINED, 1000),
- }, new long[] { 1000L, 1000L, 1000L, 1000L, 1000L });
- mDatabase.getMapper().stopAddingDocuments("2");
- try (final Cursor cursor = mDatabase.queryChildDocuments(
- strings(COLUMN_DISPLAY_NAME, COLUMN_MIME_TYPE),
- "2")) {
- assertEquals(5, cursor.getCount());
- cursor.moveToNext();
- assertEquals("audio.m4a", cursor.getString(0));
- assertEquals("audio/mp4", cursor.getString(1));
- cursor.moveToNext();
- assertEquals("video.m4v", cursor.getString(0));
- assertEquals("video/mp4", cursor.getString(1));
- cursor.moveToNext();
- // Assume that the file is video as we don't have any hints to find out if the file is
- // video or audio.
- assertEquals("unknown.mp4", cursor.getString(0));
- assertEquals("video/mp4", cursor.getString(1));
- // Don't return mime type that is inconsistent with format code.
- cursor.moveToNext();
- assertEquals("inconsistent.txt", cursor.getString(0));
- assertEquals("video/mpeg", cursor.getString(1));
- cursor.moveToNext();
- assertEquals("noext", cursor.getString(0));
- assertEquals("application/octet-stream", cursor.getString(1));
- }
- }
-
- private void addTestDevice() throws FileNotFoundException {
- TestUtil.addTestDevice(mDatabase);
- }
-
- private void addTestStorage(String parentId) throws FileNotFoundException {
- TestUtil.addTestStorage(mDatabase, parentId);
- }
-}
diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java
deleted file mode 100644
index 65c86df..0000000
--- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java
+++ /dev/null
@@ -1,1040 +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.mtp;
-
-import android.database.Cursor;
-import android.mtp.MtpConstants;
-import android.mtp.MtpObjectInfo;
-import android.net.Uri;
-import android.os.ParcelFileDescriptor;
-import android.os.storage.StorageManager;
-import android.provider.DocumentsContract.Document;
-import android.provider.DocumentsContract.Path;
-import android.provider.DocumentsContract.Root;
-import android.system.Os;
-import android.system.OsConstants;
-import android.provider.DocumentsContract;
-import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.MediumTest;
-
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.util.Arrays;
-import java.util.LinkedList;
-import java.util.Queue;
-import java.util.concurrent.TimeoutException;
-
-import static com.android.mtp.MtpDatabase.strings;
-import static com.android.mtp.TestUtil.OPERATIONS_SUPPORTED;
-
-@MediumTest
-public class MtpDocumentsProviderTest extends AndroidTestCase {
- private final static Uri ROOTS_URI =
- DocumentsContract.buildRootsUri(MtpDocumentsProvider.AUTHORITY);
- private TestContentResolver mResolver;
- private MtpDocumentsProvider mProvider;
- private TestMtpManager mMtpManager;
- private final TestResources mResources = new TestResources();
- private MtpDatabase mDatabase;
-
- @Override
- public void setUp() throws IOException {
- mResolver = new TestContentResolver();
- mMtpManager = new TestMtpManager(getContext());
- }
-
- @Override
- public void tearDown() {
- mProvider.shutdown();
- MtpDatabase.deleteDatabase(getContext());
- }
-
- public void testOpenAndCloseDevice() throws Exception {
- setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
- mMtpManager.addValidDevice(new MtpDeviceRecord(
- 0,
- "Device A",
- null /* deviceKey */,
- false /* unopened */,
- new MtpRoot[] {
- new MtpRoot(
- 0 /* deviceId */,
- 1 /* storageId */,
- "Storage A" /* volume description */,
- 1024 /* free space */,
- 2048 /* total space */,
- "" /* no volume identifier */)
- },
- OPERATIONS_SUPPORTED,
- null));
-
- mProvider.resumeRootScanner();
- mResolver.waitForNotification(ROOTS_URI, 1);
-
- mProvider.openDevice(0);
- mResolver.waitForNotification(ROOTS_URI, 2);
-
- mProvider.closeDevice(0);
- mResolver.waitForNotification(ROOTS_URI, 3);
- }
-
- public void testOpenAndCloseErrorDevice() throws Exception {
- setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
- try {
- mProvider.openDevice(1);
- fail();
- } catch (Throwable error) {
- assertTrue(error instanceof IOException);
- }
- assertEquals(0, mProvider.getOpenedDeviceRecordsCache().length);
-
- // Check if the following notification is the first one or not.
- mMtpManager.addValidDevice(new MtpDeviceRecord(
- 0,
- "Device A",
- null /* deviceKey */,
- false /* unopened */,
- new MtpRoot[] {
- new MtpRoot(
- 0 /* deviceId */,
- 1 /* storageId */,
- "Storage A" /* volume description */,
- 1024 /* free space */,
- 2048 /* total space */,
- "" /* no volume identifier */)
- },
- OPERATIONS_SUPPORTED,
- null));
- mProvider.resumeRootScanner();
- mResolver.waitForNotification(ROOTS_URI, 1);
- mProvider.openDevice(0);
- mResolver.waitForNotification(ROOTS_URI, 2);
- }
-
- public void testOpenDeviceOnDemand() throws Exception {
- setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
- mMtpManager.addValidDevice(new MtpDeviceRecord(
- 0,
- "Device A",
- null /* deviceKey */,
- false /* unopened */,
- new MtpRoot[] {
- new MtpRoot(
- 0 /* deviceId */,
- 1 /* storageId */,
- "Storage A" /* volume description */,
- 1024 /* free space */,
- 2048 /* total space */,
- "" /* no volume identifier */)
- },
- OPERATIONS_SUPPORTED,
- null));
- mMtpManager.setObjectHandles(0, 1, -1, new int[0]);
- mProvider.resumeRootScanner();
- mResolver.waitForNotification(ROOTS_URI, 1);
- final String[] columns = new String[] {
- DocumentsContract.Root.COLUMN_TITLE,
- DocumentsContract.Root.COLUMN_DOCUMENT_ID
- };
- try (final Cursor cursor = mProvider.queryRoots(columns)) {
- assertEquals(1, cursor.getCount());
- assertTrue(cursor.moveToNext());
- assertEquals("Device A", cursor.getString(0));
- assertEquals(1, cursor.getLong(1));
- }
- {
- final MtpDeviceRecord[] openedDevice = mProvider.getOpenedDeviceRecordsCache();
- assertEquals(0, openedDevice.length);
- }
- // Device is opened automatically when querying its children.
- try (final Cursor cursor = mProvider.queryChildDocuments("1", null, (String) null)) {}
-
- {
- final MtpDeviceRecord[] openedDevice = mProvider.getOpenedDeviceRecordsCache();
- assertEquals(1, openedDevice.length);
- assertEquals(0, openedDevice[0].deviceId);
- }
- }
-
- public void testQueryRoots() throws Exception {
- setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
- mMtpManager.addValidDevice(new MtpDeviceRecord(
- 0,
- "Device A",
- "Device key A",
- false /* unopened */,
- new MtpRoot[] {
- new MtpRoot(
- 0 /* deviceId */,
- 1 /* storageId */,
- "Storage A" /* volume description */,
- 1024 /* free space */,
- 2048 /* total space */,
- "" /* no volume identifier */)
- },
- OPERATIONS_SUPPORTED,
- null));
- mMtpManager.addValidDevice(new MtpDeviceRecord(
- 1,
- "Device B",
- "Device key B",
- false /* unopened */,
- new MtpRoot[] {
- new MtpRoot(
- 1 /* deviceId */,
- 1 /* storageId */,
- "Storage B" /* volume description */,
- 2048 /* free space */,
- 4096 /* total space */,
- "Identifier B" /* no volume identifier */)
- },
- new int[0] /* No operations supported */,
- null));
-
- {
- mProvider.openDevice(0);
- mResolver.waitForNotification(ROOTS_URI, 1);
- final Cursor cursor = mProvider.queryRoots(null);
- assertEquals(2, cursor.getCount());
- cursor.moveToNext();
- assertEquals("1", cursor.getString(0));
- assertEquals(
- Root.FLAG_SUPPORTS_IS_CHILD |
- Root.FLAG_SUPPORTS_CREATE |
- Root.FLAG_LOCAL_ONLY,
- cursor.getInt(1));
- assertEquals(R.drawable.ic_root_mtp, cursor.getInt(2));
- assertEquals("Device A Storage A", cursor.getString(3));
- assertEquals("1", cursor.getString(4));
- assertEquals(1024, cursor.getInt(5));
- }
-
- {
- mProvider.openDevice(1);
- mResolver.waitForNotification(ROOTS_URI, 2);
- final Cursor cursor = mProvider.queryRoots(null);
- assertEquals(2, cursor.getCount());
- cursor.moveToNext();
- cursor.moveToNext();
- assertEquals("2", cursor.getString(0));
- assertEquals(
- Root.FLAG_SUPPORTS_IS_CHILD | Root.FLAG_LOCAL_ONLY, cursor.getInt(1));
- assertEquals(R.drawable.ic_root_mtp, cursor.getInt(2));
- assertEquals("Device B Storage B", cursor.getString(3));
- assertEquals("2", cursor.getString(4));
- assertEquals(2048, cursor.getInt(5));
- }
- }
-
- public void testQueryRoots_error() throws Exception {
- setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
- mMtpManager.addValidDevice(new MtpDeviceRecord(
- 0,
- "Device A",
- "Device key A",
- false /* unopened */,
- new MtpRoot[0],
- OPERATIONS_SUPPORTED,
- null));
- mMtpManager.addValidDevice(new MtpDeviceRecord(
- 1,
- "Device B",
- "Device key B",
- false /* unopened */,
- new MtpRoot[] {
- new MtpRoot(
- 1 /* deviceId */,
- 1 /* storageId */,
- "Storage B" /* volume description */,
- 2048 /* free space */,
- 4096 /* total space */,
- "Identifier B" /* no volume identifier */)
- },
- OPERATIONS_SUPPORTED,
- null));
- {
- mProvider.openDevice(0);
- mResolver.waitForNotification(ROOTS_URI, 1);
-
- mProvider.openDevice(1);
- mResolver.waitForNotification(ROOTS_URI, 2);
-
- final Cursor cursor = mProvider.queryRoots(null);
- assertEquals(2, cursor.getCount());
-
- cursor.moveToNext();
- assertEquals("1", cursor.getString(0));
- assertEquals(
- Root.FLAG_SUPPORTS_IS_CHILD | Root.FLAG_SUPPORTS_CREATE | Root.FLAG_LOCAL_ONLY,
- cursor.getInt(1));
- assertEquals(R.drawable.ic_root_mtp, cursor.getInt(2));
- assertEquals("Device A", cursor.getString(3));
- assertEquals("1", cursor.getString(4));
- assertEquals(0, cursor.getInt(5));
-
- cursor.moveToNext();
- assertEquals("2", cursor.getString(0));
- assertEquals(
- Root.FLAG_SUPPORTS_IS_CHILD | Root.FLAG_SUPPORTS_CREATE | Root.FLAG_LOCAL_ONLY,
- cursor.getInt(1));
- assertEquals(R.drawable.ic_root_mtp, cursor.getInt(2));
- assertEquals("Device B Storage B", cursor.getString(3));
- assertEquals("2", cursor.getString(4));
- assertEquals(2048, cursor.getInt(5));
- }
- }
-
- public void testQueryDocument() throws IOException, InterruptedException, TimeoutException {
- setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
- setupRoots(0, new MtpRoot[] { new MtpRoot(0, 0, "Storage", 1000, 1000, "") });
- setupDocuments(
- 0,
- 0,
- MtpManager.OBJECT_HANDLE_ROOT_CHILDREN,
- "1",
- new MtpObjectInfo[] {
- new MtpObjectInfo.Builder()
- .setObjectHandle(100)
- .setFormat(MtpConstants.FORMAT_EXIF_JPEG)
- .setName("image.jpg")
- .setDateModified(1422716400000L)
- .setCompressedSize(1024 * 1024 * 5)
- .setThumbCompressedSize(50 * 1024)
- .build()
- });
-
- final Cursor cursor = mProvider.queryDocument("3", null);
- assertEquals(1, cursor.getCount());
-
- cursor.moveToNext();
-
- assertEquals("3", cursor.getString(0));
- assertEquals("image/jpeg", cursor.getString(1));
- assertEquals("image.jpg", cursor.getString(2));
- assertEquals(1422716400000L, cursor.getLong(3));
- assertEquals(
- DocumentsContract.Document.FLAG_SUPPORTS_DELETE |
- DocumentsContract.Document.FLAG_SUPPORTS_WRITE |
- DocumentsContract.Document.FLAG_SUPPORTS_THUMBNAIL |
- DocumentsContract.Document.FLAG_SUPPORTS_METADATA,
- cursor.getInt(4));
- assertEquals(1024 * 1024 * 5, cursor.getInt(5));
- }
-
- public void testQueryDocument_directory()
- throws IOException, InterruptedException, TimeoutException {
- setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
- setupRoots(0, new MtpRoot[] { new MtpRoot(0, 0, "Storage", 1000, 1000, "") });
- setupDocuments(
- 0,
- 0,
- MtpManager.OBJECT_HANDLE_ROOT_CHILDREN,
- "1",
- new MtpObjectInfo[] {
- new MtpObjectInfo.Builder()
- .setObjectHandle(2)
- .setStorageId(1)
- .setFormat(MtpConstants.FORMAT_ASSOCIATION)
- .setName("directory")
- .setDateModified(1422716400000L)
- .build()
- });
-
- final Cursor cursor = mProvider.queryDocument("3", null);
- assertEquals(1, cursor.getCount());
-
- cursor.moveToNext();
- assertEquals("3", cursor.getString(0));
- assertEquals(DocumentsContract.Document.MIME_TYPE_DIR, cursor.getString(1));
- assertEquals("directory", cursor.getString(2));
- assertEquals(1422716400000L, cursor.getLong(3));
- assertEquals(
- DocumentsContract.Document.FLAG_SUPPORTS_DELETE |
- DocumentsContract.Document.FLAG_DIR_SUPPORTS_CREATE,
- cursor.getInt(4));
- assertEquals(0, cursor.getInt(5));
- }
-
- public void testQueryDocument_forStorage()
- throws IOException, InterruptedException, TimeoutException {
- setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
- setupRoots(0, new MtpRoot[] {
- new MtpRoot(
- 0 /* deviceId */,
- 1 /* storageId */,
- "Storage A" /* volume description */,
- 1024 /* free space */,
- 4096 /* total space */,
- "" /* no volume identifier */)
- });
- final Cursor cursor = mProvider.queryDocument("2", null);
- assertEquals(1, cursor.getCount());
-
- cursor.moveToNext();
- assertEquals("2", cursor.getString(0));
- assertEquals(DocumentsContract.Document.MIME_TYPE_DIR, cursor.getString(1));
- assertEquals("Storage A", cursor.getString(2));
- assertTrue(cursor.isNull(3));
- assertEquals(DocumentsContract.Document.FLAG_DIR_SUPPORTS_CREATE, cursor.getInt(4));
- assertEquals(3072, cursor.getInt(5));
- }
-
- public void testQueryDocument_forDeviceWithSingleStorage()
- throws IOException, InterruptedException, TimeoutException {
- setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
- setupRoots(0, new MtpRoot[] {
- new MtpRoot(
- 0 /* deviceId */,
- 1 /* storageId */,
- "Storage A" /* volume description */,
- 1024 /* free space */,
- 4096 /* total space */,
- "" /* no volume identifier */)
- });
- final Cursor cursor = mProvider.queryDocument("1", null);
- assertEquals(1, cursor.getCount());
-
- cursor.moveToNext();
- assertEquals("1", cursor.getString(0));
- assertEquals(DocumentsContract.Document.MIME_TYPE_DIR, cursor.getString(1));
- assertEquals("Device Storage A", cursor.getString(2));
- assertTrue(cursor.isNull(3));
- assertEquals(DocumentsContract.Document.FLAG_DIR_SUPPORTS_CREATE, cursor.getInt(4));
- assertTrue(cursor.isNull(5));
- }
-
- public void testQueryDocument_forDeviceWithTwoStorages()
- throws IOException, InterruptedException, TimeoutException {
- setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
- setupRoots(0, new MtpRoot[] {
- new MtpRoot(
- 0 /* deviceId */,
- 1 /* storageId */,
- "Storage A" /* volume description */,
- 1024 /* free space */,
- 4096 /* total space */,
- "" /* no volume identifier */),
- new MtpRoot(
- 0 /* deviceId */,
- 2 /* storageId */,
- "Storage B" /* volume description */,
- 1024 /* free space */,
- 4096 /* total space */,
- "" /* no volume identifier */)
- });
- final Cursor cursor = mProvider.queryDocument("1", null);
- assertEquals(1, cursor.getCount());
-
- cursor.moveToNext();
- assertEquals("1", cursor.getString(0));
- assertEquals(DocumentsContract.Document.MIME_TYPE_DIR, cursor.getString(1));
- assertEquals("Device", cursor.getString(2));
- assertTrue(cursor.isNull(3));
- assertEquals(0, cursor.getInt(4));
- assertTrue(cursor.isNull(5));
- }
-
- public void testQueryChildDocuments() throws Exception {
- setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
- setupRoots(0, new MtpRoot[] { new MtpRoot(0, 0, "Storage", 1000, 1000, "") });
- setupDocuments(
- 0,
- 0,
- MtpManager.OBJECT_HANDLE_ROOT_CHILDREN,
- "1",
- new MtpObjectInfo[] {
- new MtpObjectInfo.Builder()
- .setObjectHandle(100)
- .setFormat(MtpConstants.FORMAT_EXIF_JPEG)
- .setName("image.jpg")
- .setCompressedSize(1024 * 1024 * 5)
- .setThumbCompressedSize(5 * 1024)
- .setProtectionStatus(MtpConstants.PROTECTION_STATUS_READ_ONLY)
- .build()
- });
-
- final Cursor cursor = mProvider.queryChildDocuments("1", null, (String) null);
- assertEquals(1, cursor.getCount());
-
- assertTrue(cursor.moveToNext());
- assertEquals("3", cursor.getString(0));
- assertEquals("image/jpeg", cursor.getString(1));
- assertEquals("image.jpg", cursor.getString(2));
- assertEquals(0, cursor.getLong(3));
- assertEquals(Document.FLAG_SUPPORTS_THUMBNAIL
- | Document.FLAG_SUPPORTS_METADATA, cursor.getInt(4));
- assertEquals(1024 * 1024 * 5, cursor.getInt(5));
-
- cursor.close();
- }
-
- public void testQueryChildDocuments_cursorError() throws Exception {
- setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
- try {
- mProvider.queryChildDocuments("1", null, (String) null);
- fail();
- } catch (FileNotFoundException error) {}
- }
-
- public void testQueryChildDocuments_documentError() throws Exception {
- setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
- setupRoots(0, new MtpRoot[] { new MtpRoot(0, 0, "Storage", 1000, 1000, "") });
- mMtpManager.setObjectHandles(0, 0, -1, new int[] { 1 });
- try (final Cursor cursor = mProvider.queryChildDocuments("1", null, (String) null)) {
- assertEquals(0, cursor.getCount());
- assertFalse(cursor.getExtras().getBoolean(DocumentsContract.EXTRA_LOADING));
- }
- }
-
- public void testDeleteDocument() throws IOException, InterruptedException, TimeoutException {
- setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
- setupRoots(0, new MtpRoot[] {
- new MtpRoot(0, 0, "Storage", 0, 0, "")
- });
- setupDocuments(0, 0, MtpManager.OBJECT_HANDLE_ROOT_CHILDREN, "1", new MtpObjectInfo[] {
- new MtpObjectInfo.Builder()
- .setName("test.txt")
- .setObjectHandle(1)
- .setParent(-1)
- .build()
- });
-
- mProvider.deleteDocument("3");
- assertEquals(1, mResolver.getChangeCount(
- DocumentsContract.buildChildDocumentsUri(
- MtpDocumentsProvider.AUTHORITY, "1")));
- }
-
- public void testDeleteDocument_error()
- throws IOException, InterruptedException, TimeoutException {
- setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
- setupRoots(0, new MtpRoot[] {
- new MtpRoot(0, 0, "Storage", 0, 0, "")
- });
- setupDocuments(0, 0, MtpManager.OBJECT_HANDLE_ROOT_CHILDREN, "1", new MtpObjectInfo[] {
- new MtpObjectInfo.Builder()
- .setName("test.txt")
- .setObjectHandle(1)
- .setParent(-1)
- .build()
- });
- try {
- mProvider.deleteDocument("4");
- fail();
- } catch (Throwable e) {
- assertTrue(e instanceof IOException);
- }
- assertEquals(0, mResolver.getChangeCount(
- DocumentsContract.buildChildDocumentsUri(
- MtpDocumentsProvider.AUTHORITY, "1")));
- }
-
- public void testOpenDocument() throws Exception {
- setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
- setupRoots(0, new MtpRoot[] {
- new MtpRoot(0, 0, "Storage", 0, 0, "")
- });
- final byte[] bytes = "Hello world".getBytes();
- setupDocuments(0, 0, MtpManager.OBJECT_HANDLE_ROOT_CHILDREN, "1", new MtpObjectInfo[] {
- new MtpObjectInfo.Builder()
- .setName("test.txt")
- .setObjectHandle(1)
- .setCompressedSize(bytes.length)
- .setParent(-1)
- .build()
- });
- mMtpManager.setImportFileBytes(0, 1, bytes);
- try (final ParcelFileDescriptor fd = mProvider.openDocument("3", "r", null)) {
- final byte[] readBytes = new byte[5];
- assertEquals(6, Os.lseek(fd.getFileDescriptor(), 6, OsConstants.SEEK_SET));
- assertEquals(5, Os.read(fd.getFileDescriptor(), readBytes, 0, 5));
- assertTrue(Arrays.equals("world".getBytes(), readBytes));
-
- assertEquals(0, Os.lseek(fd.getFileDescriptor(), 0, OsConstants.SEEK_SET));
- assertEquals(5, Os.read(fd.getFileDescriptor(), readBytes, 0, 5));
- assertTrue(Arrays.equals("Hello".getBytes(), readBytes));
- }
- }
-
- public void testOpenDocument_shortBytes() throws Exception {
- mMtpManager = new TestMtpManager(getContext()) {
- @Override
- MtpObjectInfo getObjectInfo(int deviceId, int objectHandle) throws IOException {
- if (objectHandle == 1) {
- return new MtpObjectInfo.Builder(super.getObjectInfo(deviceId, objectHandle))
- .setObjectHandle(1).setCompressedSize(1024 * 1024).build();
- }
-
- return super.getObjectInfo(deviceId, objectHandle);
- }
- };
- setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
- setupRoots(0, new MtpRoot[] {
- new MtpRoot(0, 0, "Storage", 0, 0, "")
- });
- final byte[] bytes = "Hello world".getBytes();
- setupDocuments(0, 0, MtpManager.OBJECT_HANDLE_ROOT_CHILDREN, "1", new MtpObjectInfo[] {
- new MtpObjectInfo.Builder()
- .setName("test.txt")
- .setObjectHandle(1)
- .setCompressedSize(bytes.length)
- .setParent(-1)
- .build()
- });
- mMtpManager.setImportFileBytes(0, 1, bytes);
- try (final ParcelFileDescriptor fd = mProvider.openDocument("3", "r", null)) {
- final byte[] readBytes = new byte[1024 * 1024];
- assertEquals(11, Os.read(fd.getFileDescriptor(), readBytes, 0, readBytes.length));
- }
- }
-
- public void testOpenDocument_writing() throws Exception {
- setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
- setupRoots(0, new MtpRoot[] {
- new MtpRoot(0, 100, "Storage", 0, 0, "")
- });
- final String documentId = mProvider.createDocument("2", "text/plain", "test.txt");
- {
- final ParcelFileDescriptor fd = mProvider.openDocument(documentId, "w", null);
- try (ParcelFileDescriptor.AutoCloseOutputStream stream =
- new ParcelFileDescriptor.AutoCloseOutputStream(fd)) {
- stream.write("Hello".getBytes());
- fd.getFileDescriptor().sync();
- }
- }
- {
- final ParcelFileDescriptor fd = mProvider.openDocument(documentId, "r", null);
- try (ParcelFileDescriptor.AutoCloseInputStream stream =
- new ParcelFileDescriptor.AutoCloseInputStream(fd)) {
- final byte[] bytes = new byte[5];
- stream.read(bytes);
- assertTrue(Arrays.equals("Hello".getBytes(), bytes));
- }
- }
- }
-
- public void testBusyDevice() throws Exception {
- mMtpManager = new TestMtpManager(getContext()) {
- @Override
- synchronized MtpDeviceRecord openDevice(int deviceId)
- throws IOException {
- throw new BusyDeviceException();
- }
- };
- setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
- mMtpManager.addValidDevice(new MtpDeviceRecord(
- 0, "Device A", null /* deviceKey */, false /* unopened */, new MtpRoot[0],
- OPERATIONS_SUPPORTED, null));
-
- mProvider.resumeRootScanner();
- mResolver.waitForNotification(ROOTS_URI, 1);
-
- try (final Cursor cursor = mProvider.queryRoots(null)) {
- assertEquals(1, cursor.getCount());
- }
-
- try (final Cursor cursor = mProvider.queryChildDocuments("1", null, (String) null)) {
- assertEquals(0, cursor.getCount());
- assertEquals(
- "error_busy_device",
- cursor.getExtras().getString(DocumentsContract.EXTRA_ERROR));
- }
- }
-
- public void testLockedDevice() throws Exception {
- setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
- mMtpManager.addValidDevice(new MtpDeviceRecord(
- 0, "Device A", null, false /* unopened */, new MtpRoot[0], OPERATIONS_SUPPORTED,
- null));
-
- mProvider.resumeRootScanner();
- mResolver.waitForNotification(ROOTS_URI, 1);
-
- try (final Cursor cursor = mProvider.queryRoots(null)) {
- assertEquals(1, cursor.getCount());
- }
-
- try (final Cursor cursor = mProvider.queryChildDocuments("1", null, (String) null)) {
- assertEquals(0, cursor.getCount());
- assertEquals(
- "error_locked_device",
- cursor.getExtras().getString(DocumentsContract.EXTRA_ERROR));
- }
- }
-
- public void testMappingDisconnectedDocuments() throws Exception {
- setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
- mMtpManager.addValidDevice(new MtpDeviceRecord(
- 0,
- "Device A",
- "device key",
- true /* opened */,
- new MtpRoot[] {
- new MtpRoot(
- 0 /* deviceId */,
- 1 /* storageId */,
- "Storage A" /* volume description */,
- 1024 /* free space */,
- 2048 /* total space */,
- "" /* no volume identifier */)
- },
- OPERATIONS_SUPPORTED,
- null));
-
- final String[] names = strings("Directory A", "Directory B", "Directory C");
- final int objectHandleOffset = 100;
- for (int i = 0; i < names.length; i++) {
- final int parentHandle = i == 0 ?
- MtpManager.OBJECT_HANDLE_ROOT_CHILDREN : objectHandleOffset + i - 1;
- final int objectHandle = i + objectHandleOffset;
- mMtpManager.setObjectHandles(0, 1, parentHandle, new int[] { objectHandle });
- mMtpManager.setObjectInfo(
- 0,
- new MtpObjectInfo.Builder()
- .setName(names[i])
- .setObjectHandle(objectHandle)
- .setFormat(MtpConstants.FORMAT_ASSOCIATION)
- .setStorageId(1)
- .build());
- }
-
- mProvider.resumeRootScanner();
- mResolver.waitForNotification(ROOTS_URI, 1);
-
- final int documentIdOffset = 2;
- for (int i = 0; i < names.length; i++) {
- try (final Cursor cursor = mProvider.queryChildDocuments(
- String.valueOf(documentIdOffset + i),
- strings(Document.COLUMN_DOCUMENT_ID, Document.COLUMN_DISPLAY_NAME),
- (String) null)) {
- assertEquals(1, cursor.getCount());
- cursor.moveToNext();
- assertEquals(String.valueOf(documentIdOffset + i + 1), cursor.getString(0));
- assertEquals(names[i], cursor.getString(1));
- }
- }
-
- mProvider.closeDevice(0);
- mResolver.waitForNotification(ROOTS_URI, 2);
-
- mProvider.openDevice(0);
- mResolver.waitForNotification(ROOTS_URI, 3);
-
- for (int i = 0; i < names.length; i++) {
- mResolver.waitForNotification(DocumentsContract.buildChildDocumentsUri(
- MtpDocumentsProvider.AUTHORITY,
- String.valueOf(documentIdOffset + i)), 1);
- try (final Cursor cursor = mProvider.queryChildDocuments(
- String.valueOf(documentIdOffset + i),
- strings(Document.COLUMN_DOCUMENT_ID),
- (String) null)) {
- assertEquals(1, cursor.getCount());
- cursor.moveToNext();
- assertEquals(String.valueOf(documentIdOffset + i + 1), cursor.getString(0));
- }
- }
- }
-
- public void testCreateDocument() throws Exception {
- setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
- setupRoots(0, new MtpRoot[] {
- new MtpRoot(0, 100, "Storage A", 100, 100, null)
- });
- final String documentId = mProvider.createDocument("1", "text/plain", "note.txt");
- final Uri deviceUri = DocumentsContract.buildChildDocumentsUri(
- MtpDocumentsProvider.AUTHORITY, "1");
- final Uri storageUri = DocumentsContract.buildChildDocumentsUri(
- MtpDocumentsProvider.AUTHORITY, "2");
- mResolver.waitForNotification(storageUri, 1);
- mResolver.waitForNotification(deviceUri, 1);
- try (final Cursor cursor = mProvider.queryDocument(documentId, null)) {
- assertTrue(cursor.moveToNext());
- assertEquals(
- "note.txt",
- cursor.getString(cursor.getColumnIndex(Document.COLUMN_DISPLAY_NAME)));
- assertEquals(
- "text/plain",
- cursor.getString(cursor.getColumnIndex(Document.COLUMN_MIME_TYPE)));
- }
- }
-
- public void testCreateDocument_noWritingSupport() throws Exception {
- setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
- mMtpManager.addValidDevice(new MtpDeviceRecord(
- 0, "Device A", null /* deviceKey */, false /* unopened */,
- new MtpRoot[] {
- new MtpRoot(
- 0 /* deviceId */,
- 1 /* storageId */,
- "Storage A" /* volume description */,
- 1024 /* free space */,
- 2048 /* total space */,
- "" /* no volume identifier */)
- },
- new int[0] /* no operations supported */, null));
- mProvider.resumeRootScanner();
- mResolver.waitForNotification(ROOTS_URI, 1);
- try {
- mProvider.createDocument("1", "text/palin", "note.txt");
- fail();
- } catch (UnsupportedOperationException exception) {}
- }
-
- public void testOpenDocument_noWritingSupport() throws Exception {
- setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
- mMtpManager.addValidDevice(new MtpDeviceRecord(
- 0, "Device A", null /* deviceKey */, false /* unopened */,
- new MtpRoot[] {
- new MtpRoot(
- 0 /* deviceId */,
- 1 /* storageId */,
- "Storage A" /* volume description */,
- 1024 /* free space */,
- 2048 /* total space */,
- "" /* no volume identifier */)
- },
- new int[0] /* no operations supported */, null));
- mMtpManager.setObjectHandles(
- 0, 1, MtpManager.OBJECT_HANDLE_ROOT_CHILDREN, new int[] { 100 });
- mMtpManager.setObjectInfo(
- 0, new MtpObjectInfo.Builder().setObjectHandle(100).setName("note.txt").build());
- mProvider.resumeRootScanner();
- mResolver.waitForNotification(ROOTS_URI, 1);
- try (final Cursor cursor = mProvider.queryChildDocuments(
- "1", strings(Document.COLUMN_DOCUMENT_ID), (String) null)) {
- assertEquals(1, cursor.getCount());
- cursor.moveToNext();
- assertEquals("3", cursor.getString(0));
- }
- try {
- mProvider.openDocument("3", "w", null);
- fail();
- } catch (UnsupportedOperationException exception) {}
- }
-
- public void testObjectSizeLong() throws Exception {
- setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
- setupRoots(0, new MtpRoot[] { new MtpRoot(0, 0, "Storage", 1000, 1000, "") });
- mMtpManager.setObjectSizeLong(0, 100, MtpConstants.FORMAT_EXIF_JPEG, 0x400000000L);
- setupDocuments(
- 0,
- 0,
- MtpManager.OBJECT_HANDLE_ROOT_CHILDREN,
- "1",
- new MtpObjectInfo[] {
- new MtpObjectInfo.Builder()
- .setObjectHandle(100)
- .setFormat(MtpConstants.FORMAT_EXIF_JPEG)
- .setName("image.jpg")
- .setCompressedSize(0xffffffffl)
- .build()
- });
-
- final Cursor cursor = mProvider.queryDocument("3", new String[] {
- DocumentsContract.Document.COLUMN_SIZE
- });
- assertEquals(1, cursor.getCount());
-
- cursor.moveToNext();
- assertEquals(0x400000000L, cursor.getLong(0));
- }
-
- public void testFindDocumentPath_singleStorage_toRoot() throws Exception {
- setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
- setupRoots(0, new MtpRoot[] { new MtpRoot(0, 0, "Storage", 1000, 1000, "") });
- setupHierarchyDocuments("1");
-
- final Path path = mProvider.findDocumentPath(null, "15");
- assertEquals("1", path.getRootId());
- assertEquals(4, path.getPath().size());
- assertEquals("1", path.getPath().get(0));
- assertEquals("3", path.getPath().get(1));
- assertEquals("6", path.getPath().get(2));
- assertEquals("15", path.getPath().get(3));
- }
-
- public void testFindDocumentPath_singleStorage_toDoc() throws Exception {
- setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
- setupRoots(0, new MtpRoot[] { new MtpRoot(0, 0, "Storage", 1000, 1000, "") });
- setupHierarchyDocuments("1");
-
- final Path path = mProvider.findDocumentPath("3", "18");
- assertNull(path.getRootId());
- assertEquals(3, path.getPath().size());
- assertEquals("3", path.getPath().get(0));
- assertEquals("7", path.getPath().get(1));
- assertEquals("18", path.getPath().get(2));
- }
-
- public void testFindDocumentPath_multiStorage_toRoot() throws Exception {
- setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
- setupRoots(0, new MtpRoot[] {
- new MtpRoot(0, 0, "Storage A", 1000, 1000, ""),
- new MtpRoot(0, 1, "Storage B", 1000, 1000, "") });
- setupHierarchyDocuments("2");
-
- final Path path = mProvider.findDocumentPath(null, "16");
- assertEquals("2", path.getRootId());
- assertEquals(4, path.getPath().size());
- assertEquals("2", path.getPath().get(0));
- assertEquals("4", path.getPath().get(1));
- assertEquals("7", path.getPath().get(2));
- assertEquals("16", path.getPath().get(3));
- }
-
- public void testFindDocumentPath_multiStorage_toDoc() throws Exception {
- setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
- setupRoots(0, new MtpRoot[] {
- new MtpRoot(0, 0, "Storage A", 1000, 1000, ""),
- new MtpRoot(0, 1, "Storage B", 1000, 1000, "") });
- setupHierarchyDocuments("2");
-
- final Path path = mProvider.findDocumentPath("4", "19");
- assertNull(path.getRootId());
- assertEquals(3, path.getPath().size());
- assertEquals("4", path.getPath().get(0));
- assertEquals("8", path.getPath().get(1));
- assertEquals("19", path.getPath().get(2));
- }
-
- public void testIsChildDocument() throws Exception {
- setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
- setupRoots(0, new MtpRoot[] { new MtpRoot(0, 0, "Storage", 1000, 1000, "") });
- setupHierarchyDocuments("1");
- assertTrue(mProvider.isChildDocument("1", "1"));
- assertTrue(mProvider.isChildDocument("1", "14"));
- assertTrue(mProvider.isChildDocument("2", "14"));
- assertTrue(mProvider.isChildDocument("5", "14"));
- assertFalse(mProvider.isChildDocument("3", "14"));
- assertFalse(mProvider.isChildDocument("6", "14"));
- }
-
- private void setupProvider(int flag) {
- mDatabase = new MtpDatabase(getContext(), flag);
- mProvider = new MtpDocumentsProvider();
- final StorageManager storageManager = getContext().getSystemService(StorageManager.class);
- assertTrue(mProvider.onCreateForTesting(
- getContext(),
- mResources,
- mMtpManager,
- mResolver,
- mDatabase,
- storageManager,
- new TestServiceIntentSender()));
- }
-
- private String[] getStrings(Cursor cursor) {
- try {
- final String[] results = new String[cursor.getCount()];
- for (int i = 0; cursor.moveToNext(); i++) {
- results[i] = cursor.getString(0);
- }
- return results;
- } finally {
- cursor.close();
- }
- }
-
- private String[] setupRoots(int deviceId, MtpRoot[] roots)
- throws InterruptedException, TimeoutException, IOException {
- final int changeCount = mResolver.getChangeCount(ROOTS_URI);
- mMtpManager.addValidDevice(
- new MtpDeviceRecord(deviceId, "Device", null /* deviceKey */, false /* unopened */,
- roots, OPERATIONS_SUPPORTED, null));
- mProvider.openDevice(deviceId);
- mResolver.waitForNotification(ROOTS_URI, changeCount + 1);
- return getStrings(mProvider.queryRoots(strings(DocumentsContract.Root.COLUMN_ROOT_ID)));
- }
-
- private String[] setupDocuments(
- int deviceId,
- int storageId,
- int parentHandle,
- String parentDocumentId,
- MtpObjectInfo[] objects) throws FileNotFoundException {
- final int[] handles = new int[objects.length];
- int i = 0;
- for (final MtpObjectInfo info : objects) {
- handles[i++] = info.getObjectHandle();
- mMtpManager.setObjectInfo(deviceId, info);
- }
- mMtpManager.setObjectHandles(deviceId, storageId, parentHandle, handles);
- return getStrings(mProvider.queryChildDocuments(
- parentDocumentId,
- strings(DocumentsContract.Document.COLUMN_DOCUMENT_ID),
- (String) null));
- }
-
- static class HierarchyDocument {
- int depth;
- String documentId;
- int objectHandle;
- int parentHandle;
-
- HierarchyDocument createChildDocument(int newHandle) {
- final HierarchyDocument doc = new HierarchyDocument();
- doc.depth = depth - 1;
- doc.objectHandle = newHandle;
- doc.parentHandle = objectHandle;
- return doc;
- }
-
- MtpObjectInfo toObjectInfo() {
- return new MtpObjectInfo.Builder()
- .setName("doc_" + documentId)
- .setFormat(depth > 0 ?
- MtpConstants.FORMAT_ASSOCIATION : MtpConstants.FORMAT_TEXT)
- .setObjectHandle(objectHandle)
- .setParent(parentHandle)
- .build();
- }
- }
-
- private void setupHierarchyDocuments(String documentId) throws Exception {
- final Queue<HierarchyDocument> ids = new LinkedList<>();
- final HierarchyDocument firstDocument = new HierarchyDocument();
- firstDocument.depth = 3;
- firstDocument.documentId = documentId;
- firstDocument.objectHandle = MtpManager.OBJECT_HANDLE_ROOT_CHILDREN;
- ids.add(firstDocument);
-
- int objectHandle = 100;
- while (!ids.isEmpty()) {
- final HierarchyDocument document = ids.remove();
- final HierarchyDocument[] children = new HierarchyDocument[] {
- document.createChildDocument(objectHandle++),
- document.createChildDocument(objectHandle++),
- document.createChildDocument(objectHandle++),
- };
- final String[] childDocIds = setupDocuments(
- 0, 0, document.objectHandle, document.documentId, new MtpObjectInfo[] {
- children[0].toObjectInfo(),
- children[1].toObjectInfo(),
- children[2].toObjectInfo(),
- });
- children[0].documentId = childDocIds[0];
- children[1].documentId = childDocIds[1];
- children[2].documentId = childDocIds[2];
-
- if (children[0].depth > 0) {
- ids.add(children[0]);
- ids.add(children[1]);
- ids.add(children[2]);
- }
- }
- }
-}
diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpManagerTest.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpManagerTest.java
deleted file mode 100644
index 5ada14f..0000000
--- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpManagerTest.java
+++ /dev/null
@@ -1,164 +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.mtp;
-
-import android.content.Context;
-import android.hardware.usb.UsbDevice;
-import android.hardware.usb.UsbManager;
-import android.mtp.MtpConstants;
-import android.mtp.MtpEvent;
-import android.mtp.MtpObjectInfo;
-import android.os.CancellationSignal;
-import android.os.OperationCanceledException;
-import android.os.ParcelFileDescriptor;
-import android.os.SystemClock;
-import android.test.InstrumentationTestCase;
-
-import java.io.IOException;
-import java.util.Arrays;
-import java.util.concurrent.Callable;
-import java.util.concurrent.FutureTask;
-import java.util.concurrent.TimeUnit;
-
-@RealDeviceTest
-public class MtpManagerTest extends InstrumentationTestCase {
- private static final int TIMEOUT_MS = 1000;
- UsbManager mUsbManager;
- MtpManager mManager;
- UsbDevice mUsbDevice;
-
- @Override
- public void setUp() throws Exception {
- mUsbManager = getContext().getSystemService(UsbManager.class);
- mManager = new MtpManager(getContext());
- mUsbDevice = TestUtil.setupMtpDevice(getInstrumentation(), mUsbManager, mManager);
- }
-
- @Override
- public void tearDown() throws IOException {
- mManager.closeDevice(mUsbDevice.getDeviceId());
- }
-
- @Override
- public TestResultInstrumentation getInstrumentation() {
- return (TestResultInstrumentation) super.getInstrumentation();
- }
-
- public void testCancelEvent() throws Exception {
- final CancellationSignal signal = new CancellationSignal();
- final FutureTask<Boolean> future = new FutureTask<Boolean>(
- new Callable<Boolean>() {
- @Override
- public Boolean call() throws IOException {
- try {
- while (true) {
- mManager.readEvent(mUsbDevice.getDeviceId(), signal);
- }
- } catch (OperationCanceledException exception) {
- return true;
- }
- }
- });
- final Thread thread = new Thread(future);
- thread.start();
- SystemClock.sleep(TIMEOUT_MS);
- signal.cancel();
- assertTrue(future.get(TIMEOUT_MS, TimeUnit.MILLISECONDS));
- }
-
- public void testOperationsSupported() {
- final MtpDeviceRecord[] records = mManager.getDevices();
- assertEquals(1, records.length);
- assertNotNull(records[0].operationsSupported);
- getInstrumentation().show(Arrays.toString(records[0].operationsSupported));
- }
-
- public void testEventsSupported() {
- final MtpDeviceRecord[] records = mManager.getDevices();
- assertEquals(1, records.length);
- assertNotNull(records[0].eventsSupported);
- getInstrumentation().show(Arrays.toString(records[0].eventsSupported));
- }
-
- public void testDeviceKey() {
- final MtpDeviceRecord[] records = mManager.getDevices();
- assertEquals(1, records.length);
- assertNotNull(records[0].deviceKey);
- getInstrumentation().show("deviceKey: " + records[0].deviceKey);
- }
-
- public void testEventObjectAdded() throws Exception {
- while (true) {
- getInstrumentation().show("Please take a photo by using connected MTP device.");
- final CancellationSignal signal = new CancellationSignal();
- MtpEvent event = mManager.readEvent(mUsbDevice.getDeviceId(), signal);
- if (event.getEventCode() != MtpEvent.EVENT_OBJECT_ADDED) {
- continue;
- }
- assertTrue(event.getObjectHandle() != 0);
- break;
- }
- }
-
- public void testCreateDocumentAndGetPartialObject() throws Exception {
- int storageId = 0;
- for (final MtpDeviceRecord record : mManager.getDevices()) {
- if (record.deviceId == mUsbDevice.getDeviceId()) {
- storageId = record.roots[0].mStorageId;
- break;
- }
- }
- assertTrue("Valid storage not found.", storageId != 0);
-
- final String testFileName = "MtpManagerTest_testFile.txt";
- for (final int handle : mManager.getObjectHandles(
- mUsbDevice.getDeviceId(), storageId, MtpManager.OBJECT_HANDLE_ROOT_CHILDREN)) {
- if (mManager.getObjectInfo(mUsbDevice.getDeviceId(), handle)
- .getName().equals(testFileName)) {
- mManager.deleteDocument(mUsbDevice.getDeviceId(), handle);
- break;
- }
- }
-
- final ParcelFileDescriptor[] fds = ParcelFileDescriptor.createPipe();
- final byte[] expectedBytes = "Hello Android!".getBytes("ascii");
- try (final ParcelFileDescriptor.AutoCloseOutputStream stream =
- new ParcelFileDescriptor.AutoCloseOutputStream(fds[1])) {
- stream.write(expectedBytes);
- }
- final int objectHandle = mManager.createDocument(
- mUsbDevice.getDeviceId(),
- new MtpObjectInfo.Builder()
- .setStorageId(storageId)
- .setName(testFileName)
- .setCompressedSize(expectedBytes.length)
- .setFormat(MtpConstants.FORMAT_TEXT)
- .build(),
- fds[0]);
- final byte[] bytes = new byte[100];
- assertEquals(5, mManager.getPartialObject(
- mUsbDevice.getDeviceId(), objectHandle, 0, 5, bytes));
- assertEquals("Hello", new String(bytes, 0, 5, "ascii"));
- assertEquals(8, mManager.getPartialObject(
- mUsbDevice.getDeviceId(), objectHandle, 6, 100, bytes));
- assertEquals("Android!", new String(bytes, 0, 8, "ascii"));
- }
-
- private Context getContext() {
- return getInstrumentation().getContext();
- }
-}
diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/PipeManagerTest.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/PipeManagerTest.java
deleted file mode 100644
index 53dc3db..0000000
--- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/PipeManagerTest.java
+++ /dev/null
@@ -1,106 +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.mtp;
-
-import android.os.ParcelFileDescriptor;
-import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.MediumTest;
-
-import java.io.IOException;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.TimeUnit;
-
-@MediumTest
-public class PipeManagerTest extends AndroidTestCase {
- private static final byte[] HELLO_BYTES = new byte[] { 'h', 'e', 'l', 'l', 'o' };
-
- private TestMtpManager mtpManager;
- private ExecutorService mExecutor;
- private PipeManager mPipeManager;
- private MtpDatabase mDatabase;
-
- @Override
- public void setUp() {
- mtpManager = new TestMtpManager(getContext());
- mExecutor = Executors.newSingleThreadExecutor();
- mDatabase = new MtpDatabase(getContext(), MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
- mPipeManager = new PipeManager(mDatabase, mExecutor);
- }
-
- @Override
- protected void tearDown() throws Exception {
- assertTrue(mPipeManager.close());
- mDatabase.close();
- }
-
- public void testReadDocument_basic() throws Exception {
- mtpManager.setImportFileBytes(0, 1, HELLO_BYTES);
- final ParcelFileDescriptor descriptor = mPipeManager.readDocument(
- mtpManager,
- new Identifier(0, 0, 1, null, MtpDatabaseConstants.DOCUMENT_TYPE_OBJECT));
- assertDescriptor(descriptor, HELLO_BYTES);
- }
-
- public void testReadDocument_error() throws Exception {
- final ParcelFileDescriptor descriptor = mPipeManager.readDocument(
- mtpManager,
- new Identifier(0, 0, 1, null, MtpDatabaseConstants.DOCUMENT_TYPE_OBJECT));
- assertDescriptorError(descriptor);
- }
-
- public void testReadThumbnail_basic() throws Exception {
- mtpManager.setThumbnail(0, 1, HELLO_BYTES);
- final ParcelFileDescriptor descriptor = mPipeManager.readThumbnail(
- mtpManager,
- new Identifier(0, 0, 1, null, MtpDatabaseConstants.DOCUMENT_TYPE_OBJECT));
- assertDescriptor(descriptor, HELLO_BYTES);
- }
-
- public void testReadThumbnail_error() throws Exception {
- final ParcelFileDescriptor descriptor = mPipeManager.readThumbnail(
- mtpManager,
- new Identifier(0, 0, 1, null, MtpDatabaseConstants.DOCUMENT_TYPE_OBJECT));
- assertDescriptorError(descriptor);
- }
-
- private void assertDescriptor(ParcelFileDescriptor descriptor, byte[] expectedBytes)
- throws IOException, InterruptedException {
- mExecutor.shutdown();
- assertTrue(mExecutor.awaitTermination(1000, TimeUnit.MILLISECONDS));
- try (final ParcelFileDescriptor.AutoCloseInputStream stream =
- new ParcelFileDescriptor.AutoCloseInputStream(descriptor)) {
- byte[] results = new byte[100];
- assertEquals(expectedBytes.length, stream.read(results));
- for (int i = 0; i < expectedBytes.length; i++) {
- assertEquals(expectedBytes[i], results[i]);
- }
- }
- }
-
- private void assertDescriptorError(ParcelFileDescriptor descriptor)
- throws InterruptedException {
- mExecutor.shutdown();
- assertTrue(mExecutor.awaitTermination(1000, TimeUnit.MILLISECONDS));
- try {
- descriptor.checkError();
- fail();
- } catch (Throwable error) {
- assertTrue(error instanceof IOException);
- }
- }
-}
diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/RealDeviceTest.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/RealDeviceTest.java
deleted file mode 100644
index 22daaf2..0000000
--- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/RealDeviceTest.java
+++ /dev/null
@@ -1,26 +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.mtp;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-@Retention(RetentionPolicy.RUNTIME)
-@Target({ElementType.TYPE, ElementType.METHOD})
-@interface RealDeviceTest {}
diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/TestContentResolver.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/TestContentResolver.java
deleted file mode 100644
index 7e772c3..0000000
--- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/TestContentResolver.java
+++ /dev/null
@@ -1,62 +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.mtp;
-
-import android.database.ContentObserver;
-import android.net.Uri;
-import android.test.mock.MockContentResolver;
-
-import junit.framework.Assert;
-
-import java.util.HashMap;
-import java.util.Map;
-import java.util.concurrent.Phaser;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
-
-class TestContentResolver extends MockContentResolver {
- private static final int TIMEOUT_PERIOD_MS = 3000;
- private final Map<Uri, Phaser> mPhasers = new HashMap<>();
-
- @Override
- public void notifyChange(Uri uri, ContentObserver observer, boolean syncToNetwork) {
- getPhaser(uri).arrive();
- }
-
-
- void waitForNotification(Uri uri, int count) throws InterruptedException, TimeoutException {
- Assert.assertEquals(count, getPhaser(uri).awaitAdvanceInterruptibly(
- count - 1, TIMEOUT_PERIOD_MS, TimeUnit.MILLISECONDS));
- }
-
- int getChangeCount(Uri uri) {
- if (mPhasers.containsKey(uri)) {
- return mPhasers.get(uri).getPhase();
- } else {
- return 0;
- }
- }
-
- private synchronized Phaser getPhaser(Uri uri) {
- Phaser phaser = mPhasers.get(uri);
- if (phaser == null) {
- phaser = new Phaser(1);
- mPhasers.put(uri, phaser);
- }
- return phaser;
- }
-}
diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/TestMtpManager.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/TestMtpManager.java
deleted file mode 100644
index f20bbec..0000000
--- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/TestMtpManager.java
+++ /dev/null
@@ -1,236 +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.mtp;
-
-import android.content.Context;
-import android.mtp.MtpObjectInfo;
-import android.os.ParcelFileDescriptor;
-import android.util.SparseArray;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.Map;
-import junit.framework.Assert;
-
-public class TestMtpManager extends MtpManager {
- public static final int CREATED_DOCUMENT_HANDLE = 1000;
-
- protected static String pack(int... args) {
- return Arrays.toString(args);
- }
-
- private final SparseArray<MtpDeviceRecord> mDevices = new SparseArray<>();
- private final Map<String, MtpObjectInfo> mObjectInfos = new HashMap<>();
- private final Map<String, int[]> mObjectHandles = new HashMap<>();
- private final Map<String, byte[]> mThumbnailBytes = new HashMap<>();
- private final Map<String, byte[]> mImportFileBytes = new HashMap<>();
- private final Map<String, Long> mObjectSizeLongs = new HashMap<>();
-
- TestMtpManager(Context context) {
- super(context);
- }
-
- void addValidDevice(MtpDeviceRecord device) {
- mDevices.put(device.deviceId, device);
- }
-
- void setObjectHandles(int deviceId, int storageId, int parentHandle, int[] objectHandles) {
- mObjectHandles.put(pack(deviceId, storageId, parentHandle), objectHandles);
- }
-
- void setObjectInfo(int deviceId, MtpObjectInfo objectInfo) {
- mObjectInfos.put(pack(deviceId, objectInfo.getObjectHandle()), objectInfo);
- }
-
- void setImportFileBytes(int deviceId, int objectHandle, byte[] bytes) {
- mImportFileBytes.put(pack(deviceId, objectHandle), bytes);
- }
-
- byte[] getImportFileBytes(int deviceId, int objectHandle) {
- return mImportFileBytes.get(pack(deviceId, objectHandle));
- }
-
- void setThumbnail(int deviceId, int objectHandle, byte[] bytes) {
- mThumbnailBytes.put(pack(deviceId, objectHandle), bytes);
- }
-
- void setObjectSizeLong(int deviceId, int objectHandle, int format, long value) {
- mObjectSizeLongs.put(pack(deviceId, objectHandle, format), value);
- }
-
- @Override
- synchronized MtpDeviceRecord[] getDevices() {
- final MtpDeviceRecord[] result = new MtpDeviceRecord[mDevices.size()];
- for (int i = 0; i < mDevices.size(); i++) {
- final MtpDeviceRecord device = mDevices.valueAt(i);
- if (device.opened) {
- result[i] = device;
- } else {
- result[i] = new MtpDeviceRecord(
- device.deviceId, device.name, device.deviceKey, device.opened,
- new MtpRoot[0], null, null);
- }
- }
- return result;
- }
-
- @Override
- synchronized MtpDeviceRecord openDevice(int deviceId) throws IOException {
- final MtpDeviceRecord device = mDevices.get(deviceId);
- if (device == null) {
- throw new IOException();
- }
- final MtpDeviceRecord record = new MtpDeviceRecord(
- device.deviceId, device.name, device.deviceKey, true, device.roots,
- device.operationsSupported, device.eventsSupported);
- mDevices.put(deviceId, record);
- return record;
- }
-
- @Override
- synchronized void closeDevice(int deviceId) throws IOException {
- final MtpDeviceRecord device = mDevices.get(deviceId);
- if (device == null) {
- throw new IOException();
- }
- mDevices.put(
- deviceId,
- new MtpDeviceRecord(device.deviceId, device.name, device.deviceKey, false,
- device.roots, device.operationsSupported, device.eventsSupported));
- }
-
- @Override
- MtpObjectInfo getObjectInfo(int deviceId, int objectHandle) throws IOException {
- final String key = pack(deviceId, objectHandle);
- if (mObjectInfos.containsKey(key)) {
- return mObjectInfos.get(key);
- } else {
- throw new IOException("getObjectInfo error: " + key);
- }
- }
-
- @Override
- int[] getObjectHandles(int deviceId, int storageId, int parentObjectHandle) throws IOException {
- final String key = pack(deviceId, storageId, parentObjectHandle);
- if (mObjectHandles.containsKey(key)) {
- return mObjectHandles.get(key);
- } else {
- throw new IOException("getObjectHandles error: " + key);
- }
- }
-
- @Override
- void importFile(int deviceId, int objectHandle, ParcelFileDescriptor target)
- throws IOException {
- final String key = pack(deviceId, objectHandle);
- if (mImportFileBytes.containsKey(key)) {
- try (final ParcelFileDescriptor.AutoCloseOutputStream outputStream =
- new ParcelFileDescriptor.AutoCloseOutputStream(target)) {
- outputStream.write(mImportFileBytes.get(key));
- }
- } else {
- throw new IOException("importFile error: " + key);
- }
- }
-
- @Override
- int createDocument(int deviceId, MtpObjectInfo objectInfo, ParcelFileDescriptor source)
- throws IOException {
- Assert.assertNotSame(0, objectInfo.getStorageId());
- Assert.assertNotSame(-1, objectInfo.getStorageId());
- Assert.assertNotSame(0, objectInfo.getParent());
- final String key = pack(deviceId, CREATED_DOCUMENT_HANDLE);
- if (mObjectInfos.containsKey(key)) {
- throw new IOException();
- }
- final MtpObjectInfo newInfo = new MtpObjectInfo.Builder(objectInfo).
- setObjectHandle(CREATED_DOCUMENT_HANDLE).build();
- mObjectInfos.put(key, newInfo);
- if (objectInfo.getFormat() != 0x3001) {
- try (final ParcelFileDescriptor.AutoCloseInputStream inputStream =
- new ParcelFileDescriptor.AutoCloseInputStream(source)) {
- final byte[] buffer = new byte[objectInfo.getCompressedSize()];
- if (inputStream.read(buffer, 0, objectInfo.getCompressedSize()) !=
- objectInfo.getCompressedSize()) {
- throw new IOException();
- }
-
- mImportFileBytes.put(pack(deviceId, CREATED_DOCUMENT_HANDLE), buffer);
- }
- }
- return CREATED_DOCUMENT_HANDLE;
- }
-
- @Override
- byte[] getThumbnail(int deviceId, int objectHandle) throws IOException {
- final String key = pack(deviceId, objectHandle);
- if (mThumbnailBytes.containsKey(key)) {
- return mThumbnailBytes.get(key);
- } else {
- throw new IOException("getThumbnail error: " + key);
- }
- }
-
- @Override
- void deleteDocument(int deviceId, int objectHandle) throws IOException {
- final String key = pack(deviceId, objectHandle);
- if (mObjectInfos.containsKey(key)) {
- mObjectInfos.remove(key);
- } else {
- throw new IOException();
- }
- }
-
- @Override
- int getParent(int deviceId, int objectHandle) throws IOException {
- final String key = pack(deviceId, objectHandle);
- if (mObjectInfos.containsKey(key)) {
- return mObjectInfos.get(key).getParent();
- } else {
- throw new IOException();
- }
- }
-
- @Override
- byte[] getObject(int deviceId, int objectHandle, int expectedSize) throws IOException {
- return mImportFileBytes.get(pack(deviceId, objectHandle));
- }
-
- @Override
- long getPartialObject(int deviceId, int objectHandle, long offset, long size, byte[] buffer)
- throws IOException {
- final byte[] bytes = mImportFileBytes.get(pack(deviceId, objectHandle));
- int i = 0;
- while (i < size && i + offset < bytes.length) {
- buffer[i] = bytes[(int) (i + offset)];
- i++;
- }
- return i;
- }
-
- @Override
- long getObjectSizeLong(int deviceId, int objectHandle, int format) throws IOException {
- final String key = pack(deviceId, objectHandle, format);
- if (mObjectSizeLongs.containsKey(key)) {
- return mObjectSizeLongs.get(key);
- } else {
- throw new IOException();
- }
- }
-}
diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/TestResources.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/TestResources.java
deleted file mode 100644
index 8676b5a..0000000
--- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/TestResources.java
+++ /dev/null
@@ -1,39 +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.mtp;
-
-import android.test.mock.MockResources;
-
-class TestResources extends MockResources {
- @Override
- public String getString(int id) throws NotFoundException {
- switch (id) {
- case R.string.root_name:
- return "%1$s %2$s";
- case R.string.error_busy_device:
- return "error_busy_device";
- case R.string.error_locked_device:
- return "error_locked_device";
- }
- throw new NotFoundException();
- }
-
- @Override
- public String getString(int id, Object... formatArgs) throws NotFoundException {
- return String.format(getString(id), formatArgs);
- }
-}
diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/TestResultActivity.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/TestResultActivity.java
deleted file mode 100644
index 9f2bb2a..0000000
--- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/TestResultActivity.java
+++ /dev/null
@@ -1,63 +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.mtp;
-
-import android.app.Activity;
-import android.content.Context;
-import android.content.Intent;
-import android.os.Bundle;
-import android.util.Log;
-import android.view.ViewGroup.LayoutParams;
-import android.widget.LinearLayout;
-import android.widget.TextView;
-
-
-/**
- * Activity that shows the test results instead of adb while using USB port to connect MTP device.
- */
-public class TestResultActivity extends Activity {
- private final static String TAG = "MtpDocumentsProviderTest";
- private TextView mTextView;
-
- static void show(Context context, String message) {
- Log.d(TAG, message);
- final Intent intent = new Intent(context, TestResultActivity.class);
- intent.putExtra("message", message);
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- context.startActivity(intent);
- }
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- final LinearLayout linearLayout = new LinearLayout(this);
- linearLayout.setOrientation(LinearLayout.VERTICAL);
- setContentView(linearLayout);
-
- mTextView = new TextView(this);
- mTextView.setText(getIntent().getStringExtra("message") + "\n");
- linearLayout.addView(
- mTextView, new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
- }
-
- @Override
- protected void onNewIntent(Intent intent) {
- super.onNewIntent(intent);
- mTextView.setText(mTextView.getText() + intent.getStringExtra("message") + "\n");
- }
-}
diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/TestResultInstrumentation.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/TestResultInstrumentation.java
deleted file mode 100644
index 4e4cf78..0000000
--- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/TestResultInstrumentation.java
+++ /dev/null
@@ -1,87 +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.mtp;
-
-import android.os.Bundle;
-import android.test.InstrumentationTestRunner;
-
-import junit.framework.AssertionFailedError;
-import junit.framework.Test;
-import junit.framework.TestListener;
-
-/**
- * Instrumentation that can show the test result in the TestResultActivity.
- * It's useful when it runs testcases with a real USB device and could not use USB port for ADB.
- */
-public class TestResultInstrumentation extends InstrumentationTestRunner implements TestListener {
- private boolean mHasError = false;
-
- @Override
- public void onCreate(Bundle arguments) {
- if (arguments == null) {
- arguments = new Bundle();
- }
- final boolean includeRealDeviceTest =
- Boolean.parseBoolean(arguments.getString("realDeviceTest", "false"));
- if (!includeRealDeviceTest) {
- arguments.putString("notAnnotation", "com.android.mtp.RealDeviceTest");
- }
- super.onCreate(arguments);
- if (includeRealDeviceTest) {
- // Show the test result by using activity because we need to disconnect USB cable
- // from adb host while testing with real MTP device.
- addTestListener(this);
- }
- }
-
- @Override
- public void addError(Test test, Throwable t) {
- mHasError = true;
- show("ERROR", test, t);
- }
-
- @Override
- public void addFailure(Test test, AssertionFailedError t) {
- mHasError = true;
- show("FAIL", test, t);
- }
-
- @Override
- public void endTest(Test test) {
- if (!mHasError) {
- show("PASS", test, null);
- }
- }
-
- @Override
- public void startTest(Test test) {
- mHasError = false;
- }
-
- void show(String message) {
- TestResultActivity.show(getContext(), " " + message);
- }
-
- private void show(String tag, Test test, Throwable t) {
- String message = "";
- if (t != null && t.getMessage() != null) {
- message = t.getMessage();
- }
- TestResultActivity.show(
- getContext(), String.format("[%s] %s %s", tag, test.toString(), message));
- }
-}
diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/TestServiceIntentSender.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/TestServiceIntentSender.java
deleted file mode 100644
index 17b3086..0000000
--- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/TestServiceIntentSender.java
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (C) 2016 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.mtp;
-
-class TestServiceIntentSender extends ServiceIntentSender {
- @Override
- void sendUpdateNotificationIntent(MtpDeviceRecord[] record) {}
-}
diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/TestUtil.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/TestUtil.java
deleted file mode 100644
index 8805d19..0000000
--- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/TestUtil.java
+++ /dev/null
@@ -1,131 +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.mtp;
-
-import android.hardware.usb.UsbDevice;
-import android.hardware.usb.UsbDeviceConnection;
-import android.hardware.usb.UsbManager;
-import android.mtp.MtpConstants;
-import android.os.SystemClock;
-
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.util.HashMap;
-import java.util.Objects;
-
-/**
- * Static utility methods for testing.
- */
-final class TestUtil {
- private TestUtil() {}
-
- static final int[] OPERATIONS_SUPPORTED = new int[] {
- MtpConstants.OPERATION_GET_PARTIAL_OBJECT,
- MtpConstants.OPERATION_SEND_OBJECT,
- MtpConstants.OPERATION_SEND_OBJECT_INFO,
- MtpConstants.OPERATION_DELETE_OBJECT,
- MtpConstants.OPERATION_GET_OBJECT_PROP_DESC,
- MtpConstants.OPERATION_GET_OBJECT_PROP_VALUE
- };
-
- /**
- * Requests permission for a MTP device and returns the first MTP device that has at least one
- * storage.
- */
- static UsbDevice setupMtpDevice(
- TestResultInstrumentation instrumentation,
- UsbManager usbManager,
- MtpManager manager) {
- while (true) {
- try {
- final UsbDevice device = findMtpDevice(usbManager, manager);
- waitForStorages(instrumentation, manager, device.getDeviceId());
- return device;
- } catch (IOException exp) {
- instrumentation.show(Objects.toString(exp.getMessage()));
- SystemClock.sleep(1000);
- // When the MTP device is Android, and it changes the USB device type from
- // "Charging" to "MTP", the device ID will be updated. We need to find a device
- // again.
- continue;
- }
- }
- }
-
- static void addTestDevice(MtpDatabase database) throws FileNotFoundException {
- database.getMapper().startAddingDocuments(null);
- database.getMapper().putDeviceDocument(new MtpDeviceRecord(
- 0, "Device", "device_key", /* opened is */ true, new MtpRoot[0],
- OPERATIONS_SUPPORTED, null));
- database.getMapper().stopAddingDocuments(null);
- }
-
- static void addTestStorage(MtpDatabase database, String parentId) throws FileNotFoundException {
- database.getMapper().startAddingDocuments(parentId);
- database.getMapper().putStorageDocuments(parentId, OPERATIONS_SUPPORTED, new MtpRoot[] {
- new MtpRoot(0, 100, "Storage", 1024, 1024, ""),
- });
- database.getMapper().stopAddingDocuments(parentId);
- }
-
- private static UsbDevice findMtpDevice(
- UsbManager usbManager,
- MtpManager manager) throws IOException {
- final HashMap<String,UsbDevice> devices = usbManager.getDeviceList();
- if (devices.size() == 0) {
- throw new IOException("Device not found.");
- }
- final UsbDevice device = devices.values().iterator().next();
- // Tries to get ownership of the device in case that another application use it.
- if (usbManager.hasPermission(device)) {
- final UsbDeviceConnection connection = usbManager.openDevice(device);
- for (int i = 0; i < device.getInterfaceCount(); i++) {
- // Since the test runs real environment, we need to call claim interface with
- // force = true to rob interfaces from other applications.
- connection.claimInterface(device.getInterface(i), true);
- connection.releaseInterface(device.getInterface(i));
- }
- connection.close();
- }
- manager.openDevice(device.getDeviceId());
- return device;
- }
-
- private static void waitForStorages(
- TestResultInstrumentation instrumentation,
- MtpManager manager,
- int deviceId) throws IOException {
- while (true) {
- MtpDeviceRecord device = null;
- for (final MtpDeviceRecord deviceCandidate : manager.getDevices()) {
- if (deviceCandidate.deviceId == deviceId) {
- device = deviceCandidate;
- break;
- }
- }
- if (device == null) {
- throw new IOException("Device was detached.");
- }
- if (device.roots.length == 0) {
- instrumentation.show("Wait for storages.");
- SystemClock.sleep(1000);
- continue;
- }
- return;
- }
- }
-}
diff --git a/packages/PrintSpooler/res/values-or/strings.xml b/packages/PrintSpooler/res/values-or/strings.xml
index 7eeac87..f385391 100644
--- a/packages/PrintSpooler/res/values-or/strings.xml
+++ b/packages/PrintSpooler/res/values-or/strings.xml
@@ -72,7 +72,7 @@
<string name="select_to_add_printers" msgid="3800709038689830974">"ପ୍ରିଣ୍ଟର ଯୋଡ଼ିବାକୁ ଚୟନ କରନ୍ତୁ"</string>
<string name="enable_print_service" msgid="3482815747043533842">"ସକ୍ଷମ କରିବା ପାଇଁ ଚୟନ କରନ୍ତୁ"</string>
<string name="enabled_services_title" msgid="7036986099096582296">"ସକ୍ଷମ କରାଯାଇଥିବା ସର୍ଭିସ୍"</string>
- <string name="recommended_services_title" msgid="3799434882937956924">"ସୁପାରିସ କରାଯାଇଥିବା ସର୍ଭିସ୍"</string>
+ <string name="recommended_services_title" msgid="3799434882937956924">"ସୁପାରିଶ କରାଯାଇଥିବା ସର୍ଭିସ୍"</string>
<string name="disabled_services_title" msgid="7313253167968363211">"ଅକ୍ଷମ କରାଯାଇଥିବା ସର୍ଭିସ୍"</string>
<string name="all_services_title" msgid="5578662754874906455">"ସମସ୍ତ ସର୍ଭିସ୍"</string>
<plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
diff --git a/packages/SettingsLib/RadioButtonPreference/res/layout/preference_radio.xml b/packages/SettingsLib/RadioButtonPreference/res/layout/preference_radio.xml
index dcb014d..b4b4c63 100644
--- a/packages/SettingsLib/RadioButtonPreference/res/layout/preference_radio.xml
+++ b/packages/SettingsLib/RadioButtonPreference/res/layout/preference_radio.xml
@@ -65,7 +65,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:singleLine="true"
- android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Subhead"
+ android:textAppearance="?android:attr/textAppearanceListItem"
android:ellipsize="marquee"
android:fadingEdge="horizontal"/>
@@ -79,7 +79,7 @@
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
- android:textAppearance="@android:style/TextAppearance.DeviceDefault.Small"
+ android:textAppearance="?android:attr/textAppearanceSmall"
android:textAlignment="viewStart"
android:textColor="?android:attr/textColorSecondary"/>
@@ -88,7 +88,7 @@
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
- android:textAppearance="@android:style/TextAppearance.DeviceDefault.Small"
+ android:textAppearance="?android:attr/textAppearanceSmall"
android:textAlignment="viewEnd"
android:textColor="?android:attr/textColorSecondary"
android:maxLines="1"
diff --git a/packages/SettingsLib/RadioButtonPreference/src/com/android/settingslib/widget/RadioButtonPreference.java b/packages/SettingsLib/RadioButtonPreference/src/com/android/settingslib/widget/RadioButtonPreference.java
index 08287ac..05e008c 100644
--- a/packages/SettingsLib/RadioButtonPreference/src/com/android/settingslib/widget/RadioButtonPreference.java
+++ b/packages/SettingsLib/RadioButtonPreference/src/com/android/settingslib/widget/RadioButtonPreference.java
@@ -22,7 +22,6 @@
import android.view.View;
import android.widget.TextView;
-import androidx.core.content.res.TypedArrayUtils;
import androidx.preference.CheckBoxPreference;
import androidx.preference.PreferenceViewHolder;
@@ -58,32 +57,29 @@
/**
* Perform inflation from XML and apply a class-specific base style.
*
- * @param context The {@link Context} this is associated with, through which it can
- * access the current theme, resources, {@link SharedPreferences}, etc.
- * @param attrs The attributes of the XML tag that is inflating the preference
- * @param defStyleAttr An attribute in the current theme that contains a reference to a style
- * resource that supplies default values for the view. Can be 0 to not
- * look for defaults.
+ * @param context The {@link Context} this is associated with, through which it can
+ * access the current theme, resources, {@link SharedPreferences}, etc.
+ * @param attrs The attributes of the XML tag that is inflating the preference
+ * @param defStyle An attribute in the current theme that contains a reference to a style
+ * resource that supplies default values for the view. Can be 0 to not
+ * look for defaults.
*/
public RadioButtonPreference(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
- setWidgetLayoutResource(R.layout.preference_widget_radiobutton);
- setLayoutResource(R.layout.preference_radio);
- setIconSpaceReserved(false);
+ init();
}
/**
* Perform inflation from XML and apply a class-specific base style.
*
- * @param context The {@link Context} this is associated with, through which it can
- * access the current theme, resources, {@link SharedPreferences}, etc.
- * @param attrs The attributes of the XML tag that is inflating the preference
+ * @param context The {@link Context} this is associated with, through which it can
+ * access the current theme, resources, {@link SharedPreferences}, etc.
+ * @param attrs The attributes of the XML tag that is inflating the preference
*/
public RadioButtonPreference(Context context, AttributeSet attrs) {
- this(context, attrs, TypedArrayUtils.getAttr(context,
- androidx.preference.R.attr.preferenceStyle,
- android.R.attr.preferenceStyle));
+ super(context, attrs);
+ init();
}
/**
@@ -158,4 +154,10 @@
}
mAppendixVisibility = visibility;
}
+
+ private void init() {
+ setWidgetLayoutResource(R.layout.preference_widget_radiobutton);
+ setLayoutResource(R.layout.preference_radio);
+ setIconSpaceReserved(false);
+ }
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/widget/FooterPreference.java b/packages/SettingsLib/src/com/android/settingslib/widget/FooterPreference.java
index fcd7ff81..1557618 100644
--- a/packages/SettingsLib/src/com/android/settingslib/widget/FooterPreference.java
+++ b/packages/SettingsLib/src/com/android/settingslib/widget/FooterPreference.java
@@ -16,12 +16,14 @@
package com.android.settingslib.widget;
+import android.annotation.StringRes;
import android.content.Context;
import android.text.TextUtils;
import android.text.method.LinkMovementMethod;
import android.util.AttributeSet;
import android.widget.TextView;
+import androidx.annotation.NonNull;
import androidx.core.content.res.TypedArrayUtils;
import androidx.preference.Preference;
import androidx.preference.PreferenceViewHolder;
@@ -80,4 +82,60 @@
setKey(KEY_FOOTER);
}
}
+
+ /**
+ * The builder is convenient to creat a dynamic FooterPreference.
+ */
+ public static class Builder {
+ private Context mContext;
+ private String mKey;
+ private CharSequence mTitle;
+
+ public Builder(@NonNull Context context) {
+ mContext = context;
+ }
+
+ /**
+ * To set the key value of the {@link FooterPreference}.
+ * @param key The key value.
+ */
+ public Builder setKey(@NonNull String key) {
+ mKey = key;
+ return this;
+ }
+
+ /**
+ * To set the title of the {@link FooterPreference}.
+ * @param title The title.
+ */
+ public Builder setTitle(CharSequence title) {
+ mTitle = title;
+ return this;
+ }
+
+ /**
+ * To set the title of the {@link FooterPreference}.
+ * @param titleResId The resource id of the title.
+ */
+ public Builder setTitle(@StringRes int titleResId) {
+ mTitle = mContext.getText(titleResId);
+ return this;
+ }
+
+ /**
+ * To generate the {@link FooterPreference}.
+ */
+ public FooterPreference build() {
+ final FooterPreference footerPreference = new FooterPreference(mContext);
+ footerPreference.setSelectable(false);
+ if (TextUtils.isEmpty(mTitle)) {
+ throw new IllegalArgumentException("Footer title cannot be empty!");
+ }
+ footerPreference.setTitle(mTitle);
+ if (!TextUtils.isEmpty(mKey)) {
+ footerPreference.setKey(mKey);
+ }
+ return footerPreference;
+ }
+ }
}
diff --git a/packages/SettingsProvider/Android.bp b/packages/SettingsProvider/Android.bp
index 1c97fc3..e54b847 100644
--- a/packages/SettingsProvider/Android.bp
+++ b/packages/SettingsProvider/Android.bp
@@ -9,7 +9,10 @@
"telephony-common",
"ims-common",
],
- static_libs: ["junit"],
+ static_libs: [
+ "junit",
+ "SettingsLib",
+ ],
platform_apis: true,
certificate: "platform",
privileged: true,
@@ -21,11 +24,18 @@
// because this test is not an instrumentation test. (because the target runs in the system process.)
srcs: [
"test/**/*.java",
+ "src/com/android/providers/settings/SettingsBackupAgent.java",
"src/com/android/providers/settings/SettingsState.java",
"src/com/android/providers/settings/SettingsHelper.java",
],
- static_libs: ["androidx.test.rules"],
- libs: ["android.test.base"],
+ static_libs: [
+ "androidx.test.rules",
+ "SettingsLib",
+ ],
+ libs: [
+ "android.test.base",
+ "android.test.mock",
+ ],
resource_dirs: ["res"],
aaptflags: [
"--auto-add-overlay",
diff --git a/packages/SettingsProvider/AndroidManifest.xml b/packages/SettingsProvider/AndroidManifest.xml
index 9bc2d75..839899e 100644
--- a/packages/SettingsProvider/AndroidManifest.xml
+++ b/packages/SettingsProvider/AndroidManifest.xml
@@ -11,6 +11,7 @@
android:restoreAnyVersion="true"
android:icon="@mipmap/ic_launcher_settings"
android:defaultToDeviceProtectedStorage="true"
+ android:forceQueryable="true"
android:directBootAware="true">
<provider android:name="SettingsProvider"
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
index 7d56868..2286f4c 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
@@ -39,9 +39,13 @@
import android.util.ArraySet;
import android.util.BackupUtils;
import android.util.Log;
+import android.util.Slog;
+import android.view.Display;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ArrayUtils;
import com.android.internal.widget.LockPatternUtils;
+import com.android.settingslib.display.DisplayDensityUtils;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
@@ -52,11 +56,14 @@
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
+import java.io.OutputStream;
import java.time.DateTimeException;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Map;
+import java.util.Objects;
import java.util.Set;
+import java.util.concurrent.atomic.AtomicInteger;
import java.util.zip.CRC32;
/**
@@ -78,10 +85,11 @@
private static final String KEY_SOFTAP_CONFIG = "softap_config";
private static final String KEY_NETWORK_POLICIES = "network_policies";
private static final String KEY_WIFI_NEW_CONFIG = "wifi_new_config";
+ private static final String KEY_DEVICE_SPECIFIC_CONFIG = "device_specific_config";
// Versioning of the state file. Increment this version
// number any time the set of state items is altered.
- private static final int STATE_VERSION = 7;
+ private static final int STATE_VERSION = 8;
// Versioning of the Network Policies backup payload.
private static final int NETWORK_POLICIES_BACKUP_VERSION = 1;
@@ -99,8 +107,9 @@
private static final int STATE_SOFTAP_CONFIG = 7;
private static final int STATE_NETWORK_POLICIES = 8;
private static final int STATE_WIFI_NEW_CONFIG = 9;
+ private static final int STATE_DEVICE_CONFIG = 10;
- private static final int STATE_SIZE = 10; // The current number of state items
+ private static final int STATE_SIZE = 11; // The current number of state items
// Number of entries in the checksum array at various version numbers
private static final int STATE_SIZES[] = {
@@ -111,17 +120,19 @@
7, // version 4 added STATE_LOCK_SETTINGS
8, // version 5 added STATE_SOFTAP_CONFIG
9, // version 6 added STATE_NETWORK_POLICIES
- STATE_SIZE // version 7 added STATE_WIFI_NEW_CONFIG
+ 10, // version 7 added STATE_WIFI_NEW_CONFIG
+ STATE_SIZE // version 8 added STATE_DEVICE_CONFIG
};
- // Versioning of the 'full backup' format
- // Increment this version any time a new item is added
- private static final int FULL_BACKUP_VERSION = 6;
private static final int FULL_BACKUP_ADDED_GLOBAL = 2; // added the "global" entry
private static final int FULL_BACKUP_ADDED_LOCK_SETTINGS = 3; // added the "lock_settings" entry
private static final int FULL_BACKUP_ADDED_SOFTAP_CONF = 4; //added the "softap_config" entry
private static final int FULL_BACKUP_ADDED_NETWORK_POLICIES = 5; //added "network_policies"
private static final int FULL_BACKUP_ADDED_WIFI_NEW = 6; // added "wifi_new_config" entry
+ private static final int FULL_BACKUP_ADDED_DEVICE_SPECIFIC = 7; // added "device specific" entry
+ // Versioning of the 'full backup' format
+ // Increment this version any time a new item is added
+ private static final int FULL_BACKUP_VERSION = FULL_BACKUP_ADDED_DEVICE_SPECIFIC;
private static final int INTEGER_BYTE_COUNT = Integer.SIZE / Byte.SIZE;
@@ -129,11 +140,17 @@
private static final String TAG = "SettingsBackupAgent";
- private static final String[] PROJECTION = {
+ @VisibleForTesting
+ static final String[] PROJECTION = {
Settings.NameValueTable.NAME,
Settings.NameValueTable.VALUE
};
+ // Versioning of the 'device specific' section of a backup
+ // Increment this any time the format is changed or data added.
+ @VisibleForTesting
+ static final int DEVICE_SPECIFIC_VERSION = 1;
+
// the key to store the WIFI data under, should be sorted as last, so restore happens last.
// use very late unicode character to quasi-guarantee last sort position.
private static final String KEY_WIFI_SUPPLICANT = "\uffedWIFI";
@@ -161,7 +178,8 @@
KEY_GLOBAL,
}));
- private SettingsHelper mSettingsHelper;
+ @VisibleForTesting
+ SettingsHelper mSettingsHelper;
private WifiManager mWifiManager;
@@ -190,6 +208,7 @@
byte[] softApConfigData = getSoftAPConfiguration();
byte[] netPoliciesData = getNetworkPolicies();
byte[] wifiFullConfigData = getNewWifiConfigData();
+ byte[] deviceSpecificInformation = getDeviceSpecificConfiguration();
long[] stateChecksums = readOldChecksums(oldState);
@@ -215,6 +234,9 @@
stateChecksums[STATE_WIFI_NEW_CONFIG] =
writeIfChanged(stateChecksums[STATE_WIFI_NEW_CONFIG], KEY_WIFI_NEW_CONFIG,
wifiFullConfigData, data);
+ stateChecksums[STATE_DEVICE_CONFIG] =
+ writeIfChanged(stateChecksums[STATE_DEVICE_CONFIG], KEY_DEVICE_SPECIFIC_CONFIG,
+ deviceSpecificInformation, data);
writeNewChecksums(stateChecksums, newState);
}
@@ -313,6 +335,12 @@
restoreNewWifiConfigData(restoredWifiNewConfigData);
break;
+ case KEY_DEVICE_SPECIFIC_CONFIG:
+ byte[] restoredDeviceSpecificConfig = new byte[size];
+ data.readEntityData(restoredDeviceSpecificConfig, 0, size);
+ restoreDeviceSpecificConfig(restoredDeviceSpecificConfig);
+ break;
+
default :
data.skipEntityData();
@@ -591,6 +619,11 @@
private void restoreSettings(byte[] settings, int bytes, Uri contentUri,
HashSet<String> movedToGlobal, Set<String> movedToSecure) {
+ restoreSettings(settings, 0, bytes, contentUri, movedToGlobal, movedToSecure);
+ }
+
+ private void restoreSettings(byte[] settings, int pos, int bytes, Uri contentUri,
+ HashSet<String> movedToGlobal, Set<String> movedToSecure) {
if (DEBUG) {
Log.i(TAG, "restoreSettings: " + contentUri);
}
@@ -601,7 +634,8 @@
Map<String, Validator> validators = null;
if (contentUri.equals(Settings.Secure.CONTENT_URI)) {
whitelist = ArrayUtils.concatElements(String.class, Settings.Secure.SETTINGS_TO_BACKUP,
- Settings.Secure.LEGACY_RESTORE_SETTINGS);
+ Settings.Secure.LEGACY_RESTORE_SETTINGS,
+ Settings.Secure.DEVICE_SPECIFIC_SETTINGS_TO_BACKUP);
validators = Settings.Secure.VALIDATORS;
} else if (contentUri.equals(Settings.System.CONTENT_URI)) {
whitelist = ArrayUtils.concatElements(String.class, Settings.System.SETTINGS_TO_BACKUP,
@@ -616,7 +650,6 @@
}
// Restore only the white list data.
- int pos = 0;
final ArrayMap<String, String> cachedEntries = new ArrayMap<>();
ContentValues contentValues = new ContentValues(2);
SettingsHelper settingsHelper = mSettingsHelper;
@@ -940,6 +973,150 @@
}
}
+ @VisibleForTesting
+ byte[] getDeviceSpecificConfiguration() throws IOException {
+ try (ByteArrayOutputStream os = new ByteArrayOutputStream()) {
+ writeHeader(os);
+ os.write(getDeviceSpecificSettings());
+ return os.toByteArray();
+ }
+ }
+
+ @VisibleForTesting
+ void writeHeader(OutputStream os) throws IOException {
+ os.write(toByteArray(DEVICE_SPECIFIC_VERSION));
+ os.write(toByteArray(Build.MANUFACTURER));
+ os.write(toByteArray(Build.PRODUCT));
+ }
+
+ private byte[] getDeviceSpecificSettings() {
+ try (Cursor cursor =
+ getContentResolver()
+ .query(Settings.Secure.CONTENT_URI, PROJECTION, null, null, null)) {
+ return extractRelevantValues(
+ cursor, Settings.Secure.DEVICE_SPECIFIC_SETTINGS_TO_BACKUP);
+ }
+ }
+
+ /**
+ * Restore the device specific settings.
+ *
+ * @param data The byte array holding a backed up version of another devices settings.
+ * @return true if the restore succeeded, false if it was stopped.
+ */
+ @VisibleForTesting
+ boolean restoreDeviceSpecificConfig(byte[] data) {
+ // We're using an AtomicInteger to wrap the position int and allow called methods to
+ // modify it.
+ AtomicInteger pos = new AtomicInteger(0);
+ if (!isSourceAcceptable(data, pos)) {
+ return false;
+ }
+
+ Integer originalDensity = getPreviousDensity();
+
+ int dataStart = pos.get();
+ restoreSettings(
+ data, dataStart, data.length, Settings.Secure.CONTENT_URI, null, null);
+
+ updateWindowManagerIfNeeded(originalDensity);
+
+ return true;
+ }
+
+ private void updateWindowManagerIfNeeded(Integer previousDensity) {
+ int newDensity;
+ try {
+ newDensity = getForcedDensity();
+ } catch (Settings.SettingNotFoundException e) {
+ // If there's not density setting we can't perform a change.
+ return;
+ }
+
+ if (previousDensity == null || previousDensity != newDensity) {
+ // From nothing to something is a change.
+ DisplayDensityUtils.setForcedDisplayDensity(Display.DEFAULT_DISPLAY, newDensity);
+ }
+ }
+
+ private Integer getPreviousDensity() {
+ try {
+ return getForcedDensity();
+ } catch (Settings.SettingNotFoundException e) {
+ return null;
+ }
+ }
+
+ private int getForcedDensity() throws Settings.SettingNotFoundException {
+ return Settings.Secure.getInt(getContentResolver(), Settings.Secure.DISPLAY_DENSITY_FORCED);
+ }
+
+ @VisibleForTesting
+ boolean isSourceAcceptable(byte[] data, AtomicInteger pos) {
+ int version = readInt(data, pos);
+ if (version > DEVICE_SPECIFIC_VERSION) {
+ Slog.w(TAG, "Unable to restore device specific information; Backup is too new");
+ return false;
+ }
+
+ String sourceManufacturer = readString(data, pos);
+ if (!Objects.equals(Build.MANUFACTURER, sourceManufacturer)) {
+ Log.w(
+ TAG,
+ "Unable to restore device specific information; Manufacturer mismatch "
+ + "(\'"
+ + Build.MANUFACTURER
+ + "\' and \'"
+ + sourceManufacturer
+ + "\')");
+ return false;
+ }
+
+ String sourceProduct = readString(data, pos);
+ if (!Objects.equals(Build.PRODUCT, sourceProduct)) {
+ Log.w(
+ TAG,
+ "Unable to restore device specific information; Product mismatch (\'"
+ + Build.PRODUCT
+ + "\' and \'"
+ + sourceProduct
+ + "\')");
+ return false;
+ }
+
+ return true;
+ }
+
+ @VisibleForTesting
+ static byte[] toByteArray(String value) {
+ if (value == null) {
+ return toByteArray(NULL_SIZE);
+ }
+
+ byte[] stringBytes = value.getBytes();
+ byte[] sizeAndString = new byte[stringBytes.length + INTEGER_BYTE_COUNT];
+ writeInt(sizeAndString, 0, stringBytes.length);
+ writeBytes(sizeAndString, INTEGER_BYTE_COUNT, stringBytes);
+ return sizeAndString;
+ }
+
+ @VisibleForTesting
+ static byte[] toByteArray(int value) {
+ byte[] result = new byte[INTEGER_BYTE_COUNT];
+ writeInt(result, 0, value);
+ return result;
+ }
+
+ private String readString(byte[] data, AtomicInteger pos) {
+ int byteCount = readInt(data, pos);
+ if (byteCount == NULL_SIZE) {
+ return null;
+ }
+
+ int stringStart = pos.getAndAdd(byteCount);
+ return new String(data, stringStart, byteCount);
+ }
+
/**
* Write an int in BigEndian into the byte array.
* @param out byte array
@@ -947,7 +1124,7 @@
* @param value integer to write
* @return the index after adding the size of an int (4) in bytes.
*/
- private int writeInt(byte[] out, int pos, int value) {
+ private static int writeInt(byte[] out, int pos, int value) {
out[pos + 0] = (byte) ((value >> 24) & 0xFF);
out[pos + 1] = (byte) ((value >> 16) & 0xFF);
out[pos + 2] = (byte) ((value >> 8) & 0xFF);
@@ -955,11 +1132,15 @@
return pos + INTEGER_BYTE_COUNT;
}
- private int writeBytes(byte[] out, int pos, byte[] value) {
+ private static int writeBytes(byte[] out, int pos, byte[] value) {
System.arraycopy(value, 0, out, pos, value.length);
return pos + value.length;
}
+ private int readInt(byte[] in, AtomicInteger pos) {
+ return readInt(in, pos.getAndAdd(INTEGER_BYTE_COUNT));
+ }
+
private int readInt(byte[] in, int pos) {
int result = ((in[pos] & 0xFF) << 24)
| ((in[pos + 1] & 0xFF) << 16)
diff --git a/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsBackupAgentTest.java b/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsBackupAgentTest.java
new file mode 100644
index 0000000..cf8e1a5
--- /dev/null
+++ b/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsBackupAgentTest.java
@@ -0,0 +1,272 @@
+/*
+ * 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.providers.settings;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertTrue;
+
+import static org.junit.Assert.assertArrayEquals;
+
+import android.content.ContentResolver;
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.ContextWrapper;
+import android.database.Cursor;
+import android.database.MatrixCursor;
+import android.net.Uri;
+import android.os.Build;
+import android.provider.Settings;
+import android.test.mock.MockContentProvider;
+import android.test.mock.MockContentResolver;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/** Tests for the SettingsHelperTest */
+@RunWith(AndroidJUnit4.class)
+public class SettingsBackupAgentTest extends BaseSettingsProviderTest {
+
+ private static final String TEST_DISPLAY_DENSITY_FORCED = "123";
+ private static final Map<String, String> TEST_VALUES = new HashMap<>();
+
+ static {
+ TEST_VALUES.put(Settings.Secure.DISPLAY_DENSITY_FORCED, TEST_DISPLAY_DENSITY_FORCED);
+ }
+
+ private TestFriendlySettingsBackupAgent mAgentUnderTest;
+ private Context mContext;
+
+ @Before
+ public void setUp() {
+ mContext = new ContextWithMockContentResolver(getContext());
+
+ mAgentUnderTest = new TestFriendlySettingsBackupAgent();
+ mAgentUnderTest.attach(mContext);
+ }
+
+ @Test
+ public void testRoundTripDeviceSpecificSettings() throws IOException {
+ TestSettingsHelper helper = new TestSettingsHelper(mContext);
+ mAgentUnderTest.mSettingsHelper = helper;
+
+ byte[] settingsBackup = mAgentUnderTest.getDeviceSpecificConfiguration();
+
+ assertEquals("Not all values backed up.", TEST_VALUES.keySet(), helper.mReadEntries);
+
+ mAgentUnderTest.restoreDeviceSpecificConfig(settingsBackup);
+
+ assertEquals("Not all values were restored.", TEST_VALUES, helper.mWrittenValues);
+ }
+
+ @Test
+ public void testGeneratedHeaderMatchesCurrentDevice() throws IOException {
+ mAgentUnderTest.mSettingsHelper = new TestSettingsHelper(mContext);
+
+ byte[] header = generateUncorruptedHeader();
+
+ AtomicInteger pos = new AtomicInteger(0);
+ assertTrue(
+ "Generated header is not correct for device.",
+ mAgentUnderTest.isSourceAcceptable(header, pos));
+ }
+
+ @Test
+ public void testTestHeaderGeneratorIsAccurate() throws IOException {
+ byte[] classGeneratedHeader = generateUncorruptedHeader();
+ byte[] testGeneratedHeader = generateCorruptedHeader(false, false, false);
+
+ assertArrayEquals(
+ "Difference in header generation", classGeneratedHeader, testGeneratedHeader);
+ }
+
+ @Test
+ public void testNewerHeaderVersionFailsMatch() throws IOException {
+ byte[] header = generateCorruptedHeader(true, false, false);
+
+ AtomicInteger pos = new AtomicInteger(0);
+ assertFalse(
+ "Newer header does not fail match",
+ mAgentUnderTest.isSourceAcceptable(header, pos));
+ }
+
+ @Test
+ public void testWrongManufacturerFailsMatch() throws IOException {
+ byte[] header = generateCorruptedHeader(false, true, false);
+
+ AtomicInteger pos = new AtomicInteger(0);
+ assertFalse(
+ "Wrong manufacturer does not fail match",
+ mAgentUnderTest.isSourceAcceptable(header, pos));
+ }
+
+ @Test
+ public void testWrongProductFailsMatch() throws IOException {
+ byte[] header = generateCorruptedHeader(false, false, true);
+
+ AtomicInteger pos = new AtomicInteger(0);
+ assertFalse(
+ "Wrong product does not fail match",
+ mAgentUnderTest.isSourceAcceptable(header, pos));
+ }
+
+ @Test
+ public void checkAcceptTestFailingBlockRestore() {
+ mAgentUnderTest.setForcedDeviceInfoRestoreAcceptability(false);
+ byte[] data = new byte[0];
+
+ assertFalse(
+ "Blocking isSourceAcceptable did not stop restore",
+ mAgentUnderTest.restoreDeviceSpecificConfig(data));
+ }
+
+ private byte[] generateUncorruptedHeader() throws IOException {
+ try (ByteArrayOutputStream os = new ByteArrayOutputStream()) {
+ mAgentUnderTest.writeHeader(os);
+ return os.toByteArray();
+ }
+ }
+
+ private byte[] generateCorruptedHeader(
+ boolean corruptVersion, boolean corruptManufacturer, boolean corruptProduct)
+ throws IOException {
+ try (ByteArrayOutputStream os = new ByteArrayOutputStream()) {
+ int version = SettingsBackupAgent.DEVICE_SPECIFIC_VERSION;
+ if (corruptVersion) {
+ version++;
+ }
+ os.write(SettingsBackupAgent.toByteArray(version));
+
+ String manufacturer = Build.MANUFACTURER;
+ if (corruptManufacturer) {
+ manufacturer = manufacturer == null ? "X" : manufacturer + "X";
+ }
+ os.write(SettingsBackupAgent.toByteArray(manufacturer));
+
+ String product = Build.PRODUCT;
+ if (corruptProduct) {
+ product = product == null ? "X" : product + "X";
+ }
+ os.write(SettingsBackupAgent.toByteArray(product));
+
+ return os.toByteArray();
+ }
+ }
+
+ private static class TestFriendlySettingsBackupAgent extends SettingsBackupAgent {
+ private Boolean mForcedDeviceInfoRestoreAcceptability = null;
+
+ void setForcedDeviceInfoRestoreAcceptability(boolean value) {
+ mForcedDeviceInfoRestoreAcceptability = value;
+ }
+
+ @VisibleForTesting
+ boolean isSourceAcceptable(byte[] data, AtomicInteger pos) {
+ return mForcedDeviceInfoRestoreAcceptability == null
+ ? super.isSourceAcceptable(data, pos)
+ : mForcedDeviceInfoRestoreAcceptability;
+ }
+ }
+
+ /** The TestSettingsHelper tracks which values have been backed up and/or restored. */
+ private static class TestSettingsHelper extends SettingsHelper {
+ private Set<String> mReadEntries;
+ private Map<String, String> mWrittenValues;
+
+ TestSettingsHelper(Context context) {
+ super(context);
+ mReadEntries = new HashSet<>();
+ mWrittenValues = new HashMap<>();
+ }
+
+ @Override
+ public String onBackupValue(String key, String value) {
+ mReadEntries.add(key);
+ String readValue = TEST_VALUES.get(key);
+ assert readValue != null;
+ return readValue;
+ }
+
+ @Override
+ public void restoreValue(
+ Context context,
+ ContentResolver cr,
+ ContentValues contentValues,
+ Uri destination,
+ String name,
+ String value,
+ int restoredFromSdkInt) {
+ mWrittenValues.put(name, value);
+ }
+ }
+
+ /**
+ * ContextWrapper which allows us to return a MockContentResolver to code which uses it to
+ * access settings. This allows us to override the ContentProvider for the Settings URIs to
+ * return known values.
+ */
+ private static class ContextWithMockContentResolver extends ContextWrapper {
+ private MockContentResolver mContentResolver;
+
+ ContextWithMockContentResolver(Context targetContext) {
+ super(targetContext);
+
+ mContentResolver = new MockContentResolver();
+ mContentResolver.addProvider(
+ Settings.AUTHORITY, new DeviceSpecificInfoMockContentProvider());
+ }
+
+ @Override
+ public ContentResolver getContentResolver() {
+ return mContentResolver;
+ }
+ }
+
+ /** ContentProvider which returns a set of known test values. */
+ private static class DeviceSpecificInfoMockContentProvider extends MockContentProvider {
+ private static final Object[][] RESULT_ROWS = {
+ {Settings.Secure.DISPLAY_DENSITY_FORCED, TEST_DISPLAY_DENSITY_FORCED},
+ };
+
+ @Override
+ public Cursor query(
+ Uri uri,
+ String[] projection,
+ String selection,
+ String[] selectionArgs,
+ String sortOrder) {
+ MatrixCursor result = new MatrixCursor(SettingsBackupAgent.PROJECTION);
+ for (Object[] resultRow : RESULT_ROWS) {
+ result.addRow(resultRow);
+ }
+ return result;
+ }
+ }
+}
diff --git a/packages/SystemUI/res-keyguard/values-de/strings.xml b/packages/SystemUI/res-keyguard/values-de/strings.xml
index 7f39a19..d44bfbc 100644
--- a/packages/SystemUI/res-keyguard/values-de/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-de/strings.xml
@@ -152,6 +152,6 @@
<item quantity="one">Die SIM-Karte ist jetzt deaktiviert. Gib den PUK-Code ein, um fortzufahren. Du hast noch <xliff:g id="_NUMBER_0">%d</xliff:g> Versuch, bevor die SIM-Karte endgültig gesperrt wird. Weitere Informationen erhältst du von deinem Mobilfunkanbieter.</item>
</plurals>
<string name="clock_title_default" msgid="6645600990069154049">"Standard"</string>
- <string name="clock_title_bubble" msgid="1286365278681892114">"Blase"</string>
+ <string name="clock_title_bubble" msgid="1286365278681892114">"Bubble"</string>
<string name="clock_title_analog" msgid="4047401488577315053">"Analog"</string>
</resources>
diff --git a/packages/SystemUI/res/layout/keyguard_bottom_area.xml b/packages/SystemUI/res/layout/keyguard_bottom_area.xml
index 21c2c6b..1bfc4c0 100644
--- a/packages/SystemUI/res/layout/keyguard_bottom_area.xml
+++ b/packages/SystemUI/res/layout/keyguard_bottom_area.xml
@@ -24,48 +24,7 @@
android:outlineProvider="none"
android:elevation="5dp" > <!-- Put it above the status bar header -->
- <LinearLayout
- android:id="@+id/keyguard_indication_area"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginBottom="@dimen/keyguard_indication_margin_bottom"
- android:layout_gravity="bottom|center_horizontal"
- android:orientation="horizontal">
-
- <include layout="@layout/left_docked_overlay" />
-
- <LinearLayout
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- android:layout_gravity="center_vertical|center_horizontal"
- android:orientation="vertical">
-
- <com.android.systemui.statusbar.phone.KeyguardIndicationTextView
- android:id="@+id/keyguard_indication_enterprise_disclosure"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:gravity="center"
- android:paddingStart="@dimen/keyguard_indication_text_padding"
- android:paddingEnd="@dimen/keyguard_indication_text_padding"
- android:textAppearance="@style/TextAppearance.Keyguard.BottomArea"
- android:visibility="gone" />
-
- <com.android.systemui.statusbar.phone.KeyguardIndicationTextView
- android:id="@+id/keyguard_indication_text"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:gravity="center"
- android:paddingStart="@dimen/keyguard_indication_text_padding"
- android:paddingEnd="@dimen/keyguard_indication_text_padding"
- android:textAppearance="@style/TextAppearance.Keyguard.BottomArea"
- android:accessibilityLiveRegion="polite" />
-
- </LinearLayout>
-
- <include layout="@layout/right_docked_overlay" />
-
- </LinearLayout>
+ <include layout="@layout/keyguard_indication_area_overlay" />
<FrameLayout
android:id="@+id/preview_container"
diff --git a/packages/SystemUI/res/layout/keyguard_indication_area_overlay.xml b/packages/SystemUI/res/layout/keyguard_indication_area_overlay.xml
new file mode 100644
index 0000000..cc30a68
--- /dev/null
+++ b/packages/SystemUI/res/layout/keyguard_indication_area_overlay.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/keyguard_indication_area"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="@dimen/keyguard_indication_margin_bottom"
+ android:layout_gravity="bottom|center_horizontal"
+ android:orientation="vertical">
+
+ <include layout="@layout/keyguard_indication_text_view" />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/keyguard_indication_text_view.xml b/packages/SystemUI/res/layout/keyguard_indication_text_view.xml
new file mode 100644
index 0000000..2b2100c
--- /dev/null
+++ b/packages/SystemUI/res/layout/keyguard_indication_text_view.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<merge xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <com.android.systemui.statusbar.phone.KeyguardIndicationTextView
+ android:id="@+id/keyguard_indication_enterprise_disclosure"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="center"
+ android:paddingStart="@dimen/keyguard_indication_text_padding"
+ android:paddingEnd="@dimen/keyguard_indication_text_padding"
+ android:textAppearance="@style/TextAppearance.Keyguard.BottomArea"
+ android:visibility="gone"/>
+
+ <com.android.systemui.statusbar.phone.KeyguardIndicationTextView
+ android:id="@+id/keyguard_indication_text"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="center"
+ android:paddingStart="@dimen/keyguard_indication_text_padding"
+ android:paddingEnd="@dimen/keyguard_indication_text_padding"
+ android:textAppearance="@style/TextAppearance.Keyguard.BottomArea"
+ android:accessibilityLiveRegion="polite"/>
+</merge>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/left_docked_overlay.xml b/packages/SystemUI/res/layout/left_docked_overlay.xml
deleted file mode 100644
index 430143c..0000000
--- a/packages/SystemUI/res/layout/left_docked_overlay.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?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.
- -->
-
-<!-- empty stub -->
-<merge />
diff --git a/packages/SystemUI/res/layout/right_docked_overlay.xml b/packages/SystemUI/res/layout/right_docked_overlay.xml
deleted file mode 100644
index 430143c..0000000
--- a/packages/SystemUI/res/layout/right_docked_overlay.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?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.
- -->
-
-<!-- empty stub -->
-<merge />
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 08fb0b3..90ead35 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -255,8 +255,8 @@
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Lommelygten er tændt."</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Lommelygten er slukket."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Lommelygten er tændt."</string>
- <string name="accessibility_quick_settings_color_inversion_changed_off" msgid="4406577213290173911">"Invertering af farver er slået fra."</string>
- <string name="accessibility_quick_settings_color_inversion_changed_on" msgid="6897462320184911126">"Invertering af farver er slået til."</string>
+ <string name="accessibility_quick_settings_color_inversion_changed_off" msgid="4406577213290173911">"Ombytning af farver er slået fra."</string>
+ <string name="accessibility_quick_settings_color_inversion_changed_on" msgid="6897462320184911126">"Ombytning af farver er slået til."</string>
<string name="accessibility_quick_settings_hotspot_changed_off" msgid="5004708003447561394">"Mobilhotspot er slået fra."</string>
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2890951609226476206">"Mobilhotspot er slået til."</string>
<string name="accessibility_casting_turned_off" msgid="1430668982271976172">"Casting af din skærm er stoppet."</string>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index 408254f..9b3974b 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -656,7 +656,7 @@
<string name="notification_silence_title" msgid="5763240612242137433">"Lautlos"</string>
<string name="notification_alert_title" msgid="8031196611815490340">"Benachrichtigen"</string>
<string name="notification_channel_summary_low" msgid="3387466082089715555">"Benachrichtigungen werden ohne Ton oder Vibration angekündigt, um deine Konzentration nicht zu stören."</string>
- <string name="notification_channel_summary_default" msgid="5994062840431965586">"Benachrichtigungen werden mit einem Ton oder einer Vibration angekündigt, um dich auf sie aufmerksam zu machen."</string>
+ <string name="notification_channel_summary_default" msgid="5994062840431965586">"Benachrichtigungen werden mit einem Ton oder einer Vibration angekündigt."</string>
<string name="notification_unblockable_desc" msgid="4556908766584964102">"Diese Benachrichtigungen können nicht geändert werden."</string>
<string name="notification_multichannel_desc" msgid="4695920306092240550">"Die Benachrichtigungsgruppe kann hier nicht konfiguriert werden"</string>
<string name="notification_delegate_header" msgid="2857691673814814270">"Weitergeleitete Benachrichtigung"</string>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index 37aae55..d6c8d09 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -553,7 +553,7 @@
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"Ocultar"</string>
<string name="stream_voice_call" msgid="4410002696470423714">"Llamada"</string>
<string name="stream_system" msgid="7493299064422163147">"Sistema"</string>
- <string name="stream_ring" msgid="8213049469184048338">"Hacer sonar"</string>
+ <string name="stream_ring" msgid="8213049469184048338">"Timbre"</string>
<string name="stream_music" msgid="9086982948697544342">"Multimedia"</string>
<string name="stream_alarm" msgid="5209444229227197703">"Alarma"</string>
<string name="stream_notification" msgid="2563720670905665031">"Notificación"</string>
@@ -561,7 +561,7 @@
<string name="stream_dtmf" msgid="2447177903892477915">"Multifrecuencia de tono doble"</string>
<string name="stream_accessibility" msgid="301136219144385106">"Accesibilidad"</string>
<string name="ring_toggle_title" msgid="3281244519428819576">"Llamadas"</string>
- <string name="volume_ringer_status_normal" msgid="4273142424125855384">"Hacer sonar"</string>
+ <string name="volume_ringer_status_normal" msgid="4273142424125855384">"Timbre"</string>
<string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"Vibrar"</string>
<string name="volume_ringer_status_silent" msgid="6896394161022916369">"Silenciar"</string>
<string name="qs_status_phone_vibrate" msgid="204362991135761679">"Teléfono en vibración"</string>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index a3069a1..552d12e 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -886,7 +886,7 @@
<string name="qs_dnd_prompt_app" msgid="7978037419334156034">"Le mode Ne pas déranger a été activé par une application (<xliff:g id="ID_1">%s</xliff:g>)."</string>
<string name="qs_dnd_prompt_auto_rule_app" msgid="2599343675391111951">"Le mode Ne pas déranger a été activé par une règle automatique ou une application."</string>
<string name="qs_dnd_until" msgid="3469471136280079874">"Jusqu\'à <xliff:g id="ID_1">%s</xliff:g>"</string>
- <string name="qs_dnd_keep" msgid="1825009164681928736">"Garder"</string>
+ <string name="qs_dnd_keep" msgid="1825009164681928736">"Conserver"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"Remplacer"</string>
<string name="running_foreground_services_title" msgid="381024150898615683">"Applications qui fonctionnent en arrière-plan"</string>
<string name="running_foreground_services_msg" msgid="6326247670075574355">"Touchez pour afficher des détails sur l\'utilisation de la pile et des données"</string>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index 263fe8a..3fa2a48 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -46,8 +46,8 @@
<string name="bluetooth_tethered" msgid="7094101612161133267">"ब्लूटूथ टीदर किया गया"</string>
<string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"इनपुट का तरीका सेट करें"</string>
<string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"सामान्य कीबोर्ड"</string>
- <string name="usb_device_permission_prompt" msgid="1825685909587559679">"<xliff:g id="APPLICATION">%1$s</xliff:g> को <xliff:g id="USB_DEVICE">%2$s</xliff:g> के एक्सेस की अनुमति दें?"</string>
- <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"<xliff:g id="APPLICATION">%1$s</xliff:g> को <xliff:g id="USB_ACCESSORY">%2$s</xliff:g> के एक्सेस की अनुमति दें?"</string>
+ <string name="usb_device_permission_prompt" msgid="1825685909587559679">"<xliff:g id="APPLICATION">%1$s</xliff:g> को <xliff:g id="USB_DEVICE">%2$s</xliff:g> के ऐक्सेस की अनुमति दें?"</string>
+ <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"<xliff:g id="APPLICATION">%1$s</xliff:g> को <xliff:g id="USB_ACCESSORY">%2$s</xliff:g> के ऐक्सेस की अनुमति दें?"</string>
<string name="usb_device_confirm_prompt" msgid="7440562274256843905">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> के लिए <xliff:g id="APPLICATION">%1$s</xliff:g> खोलें?"</string>
<string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g> के लिए <xliff:g id="APPLICATION">%1$s</xliff:g> खोलें?"</string>
<string name="usb_accessory_uri_prompt" msgid="513450621413733343">"इस USB सहायक डिवाइस के साथ कोई भी इंस्टॉल ऐप्स काम नहीं करता. इस सहायक डिवाइस के बारे में यहां ज़्यादा जानें: <xliff:g id="URL">%1$s</xliff:g>"</string>
@@ -205,7 +205,7 @@
<string name="accessibility_overflow_action" msgid="5681882033274783311">"पूरी सूचनाएं देखें"</string>
<string name="accessibility_remove_notification" msgid="3603099514902182350">"सूचना साफ़ करें"</string>
<string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS सक्षम."</string>
- <string name="accessibility_gps_acquiring" msgid="8959333351058967158">"GPS प्राप्त करना."</string>
+ <string name="accessibility_gps_acquiring" msgid="8959333351058967158">"GPS पाना."</string>
<string name="accessibility_tty_enabled" msgid="4613200365379426561">"टेलीटाइपराइटर सक्षम."</string>
<string name="accessibility_ringer_vibrate" msgid="666585363364155055">"रिंगर कंपन (वाइब्रेशन)."</string>
<string name="accessibility_ringer_silent" msgid="9061243307939135383">"रिंगर मौन."</string>
@@ -452,8 +452,8 @@
<string name="battery_saver_notification_title" msgid="8614079794522291840">"बैटरी सेवर चालू है"</string>
<string name="battery_saver_notification_text" msgid="820318788126672692">"निष्पादन और पृष्ठभूमि डेटा को कम करता है"</string>
<string name="battery_saver_notification_action_text" msgid="132118784269455533">"बैटरी सेवर बंद करें"</string>
- <string name="media_projection_dialog_text" msgid="8585357687598538511">"रिकॉर्ड या कास्ट करते समय, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> आपकी स्क्रीन पर दिखाई जा रही या आपके डिवाइस पर चलाई जा रही संवेदनशील जानकारी एक्सेस कर सकता है. इस जानकारी में ऑडियो, पासवर्ड, भुगतान की जानकारी, फ़ोटो और मैसेज शामिल हैं."</string>
- <string name="media_projection_dialog_service_text" msgid="3075544489835858258">"रिकॉर्ड या कास्ट करते समय, यह सेवा देने वाला ऐप्लिकेशन आपकी स्क्रीन पर दिखाई जा रही या आपके डिवाइस पर चलाई जा रही संवेदनशील जानकारी एक्सेस कर सकता है. इस जानकारी में ऑडियो, पासवर्ड, भुगतान की जानकारी, फ़ोटो और मैसेज शामिल हैं."</string>
+ <string name="media_projection_dialog_text" msgid="8585357687598538511">"रिकॉर्ड या कास्ट करते समय, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> आपकी स्क्रीन पर दिखाई जा रही या आपके डिवाइस पर चलाई जा रही संवेदनशील जानकारी ऐक्सेस कर सकता है. इस जानकारी में ऑडियो, पासवर्ड, भुगतान की जानकारी, फ़ोटो और मैसेज शामिल हैं."</string>
+ <string name="media_projection_dialog_service_text" msgid="3075544489835858258">"रिकॉर्ड या कास्ट करते समय, यह सेवा देने वाला ऐप्लिकेशन आपकी स्क्रीन पर दिखाई जा रही या आपके डिवाइस पर चलाई जा रही संवेदनशील जानकारी ऐक्सेस कर सकता है. इस जानकारी में ऑडियो, पासवर्ड, भुगतान की जानकारी, फ़ोटो और मैसेज शामिल हैं."</string>
<string name="media_projection_dialog_title" msgid="8124184308671641248">"कास्ट करने/रिकॉर्ड करने के दौरान संवेदनशील जानकारी का सबके सामने आ जाना"</string>
<string name="media_projection_remember_text" msgid="3103510882172746752">"फिर से न दिखाएं"</string>
<string name="clear_all_notifications_text" msgid="814192889771462828">"सभी को हटाएं"</string>
diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml
index 20f638d..676208b 100644
--- a/packages/SystemUI/res/values-mr/strings.xml
+++ b/packages/SystemUI/res/values-mr/strings.xml
@@ -747,7 +747,7 @@
<string name="data_saver" msgid="5037565123367048522">"डेटा सेव्हर"</string>
<string name="accessibility_data_saver_on" msgid="8454111686783887148">"डेटा सेव्हर चालू आहे"</string>
<string name="accessibility_data_saver_off" msgid="8841582529453005337">"डेटा सेव्हर बंद आहे"</string>
- <string name="switch_bar_on" msgid="1142437840752794229">"चालू"</string>
+ <string name="switch_bar_on" msgid="1142437840752794229">"सुरू"</string>
<string name="switch_bar_off" msgid="8803270596930432874">"बंद"</string>
<string name="nav_bar" msgid="1993221402773877607">"नॅव्हिगेशन बार"</string>
<string name="nav_bar_layout" msgid="3664072994198772020">"लेआउट"</string>
diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml
index 83a7aaa..1f75490 100644
--- a/packages/SystemUI/res/values-sq/strings.xml
+++ b/packages/SystemUI/res/values-sq/strings.xml
@@ -544,7 +544,7 @@
<string name="screen_pinning_description_recents_invisible_accessible" msgid="6134833683151189507">"Kjo e ruan në pamje deri sa ta heqësh nga gozhdimi. Prek dhe mbaj të shtypur \"Kreu\" për ta hequr nga gozhdimi."</string>
<string name="screen_pinning_toast" msgid="2266705122951934150">"Për të hequr gozhdimin e këtij ekrani, prek dhe mbaj butonat \"Prapa\" dhe \"Përmbledhja\"."</string>
<string name="screen_pinning_toast_recents_invisible" msgid="8252402309499161281">"Për të hequr gozhdimin e këtij ekrani, prek dhe mbaj butonat \"Prapa\" dhe \"Kreu\"."</string>
- <string name="screen_pinning_positive" msgid="3783985798366751226">"E kuptova!"</string>
+ <string name="screen_pinning_positive" msgid="3783985798366751226">"E kuptova"</string>
<string name="screen_pinning_negative" msgid="3741602308343880268">"Jo, faleminderit!"</string>
<string name="screen_pinning_start" msgid="1022122128489278317">"Ekrani u gozhdua"</string>
<string name="screen_pinning_exit" msgid="5187339744262325372">"Ekrani u hoq nga gozhdimi"</string>
diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml
index 9f8f45e..6e8b097 100644
--- a/packages/SystemUI/res/values-ta/strings.xml
+++ b/packages/SystemUI/res/values-ta/strings.xml
@@ -761,7 +761,7 @@
<item msgid="8175437057325747277">"ஏதுமில்லை"</item>
</string-array>
<string-array name="nav_bar_layouts">
- <item msgid="8077901629964902399">"இயல்பானது"</item>
+ <item msgid="8077901629964902399">"சராசரி"</item>
<item msgid="8256205964297588988">"சுருக்கமானது"</item>
<item msgid="8719936228094005878">"இடப்புறம் சாய்ந்தது"</item>
<item msgid="586019486955594690">"வலப்புறம் சாய்ந்தது"</item>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index affca3d..025efac 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -741,7 +741,7 @@
<string name="battery" msgid="7498329822413202973">"Pin"</string>
<string name="clock" msgid="7416090374234785905">"Đồng hồ"</string>
<string name="headset" msgid="4534219457597457353">"Tai nghe"</string>
- <string name="accessibility_long_click_tile" msgid="6687350750091842525">"Mở cài đặt"</string>
+ <string name="accessibility_long_click_tile" msgid="6687350750091842525">"Mở phần cài đặt"</string>
<string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Đã kết nối tai nghe"</string>
<string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Đã kết nối tai nghe"</string>
<string name="data_saver" msgid="5037565123367048522">"Trình tiết kiệm dữ liệu"</string>
@@ -817,7 +817,7 @@
<string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Ứng dụng không hỗ trợ chia đôi màn hình."</string>
<string name="forced_resizable_secondary_display" msgid="4230857851756391925">"Ứng dụng có thể không hoạt động trên màn hình phụ."</string>
<string name="activity_launch_on_secondary_display_failed_text" msgid="7793821742158306742">"Ứng dụng không hỗ trợ khởi chạy trên màn hình phụ."</string>
- <string name="accessibility_quick_settings_settings" msgid="6132460890024942157">"Mở cài đặt."</string>
+ <string name="accessibility_quick_settings_settings" msgid="6132460890024942157">"Mở phần cài đặt."</string>
<string name="accessibility_quick_settings_expand" msgid="2375165227880477530">"Mở cài đặt nhanh."</string>
<string name="accessibility_quick_settings_collapse" msgid="1792625797142648105">"Đóng cài đặt nhanh."</string>
<string name="accessibility_quick_settings_alarm_set" msgid="1863000242431528676">"Đã đặt báo thức."</string>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 340cb3a..6e8e823 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -196,9 +196,6 @@
<!-- Doze: duration to avoid false pickup gestures triggered by notification vibrations -->
<integer name="doze_pickup_vibration_threshold">2000</integer>
- <!-- Doze: can we assume the pickup sensor includes a proximity check? -->
- <bool name="doze_pickup_performs_proximity_check">false</bool>
-
<!-- Type of a sensor that provides a low-power estimate of the desired display
brightness, suitable to listen to while the device is asleep (e.g. during
always-on display) -->
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/TaskKeyCache.java b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/TaskKeyCache.java
index 342cb75..8a244bf 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/TaskKeyCache.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/TaskKeyCache.java
@@ -21,6 +21,9 @@
import com.android.systemui.shared.recents.model.Task.TaskKey;
+import java.util.ArrayList;
+import java.util.Collection;
+
/**
* Base class for both strong and LRU task key cache.
*/
@@ -76,6 +79,15 @@
mKeys.remove(key.id);
}
+ /** @return {@link Collection} of {@link TaskKey} */
+ public Collection<TaskKey> getValues() {
+ Collection<TaskKey> result = new ArrayList<>(mKeys.size());
+ for (int i = 0; i < mKeys.size(); i++) {
+ result.add(mKeys.valueAt(i));
+ }
+ return result;
+ }
+
/** Removes all the entries in the cache. */
public final synchronized void evictAll() {
evictAllCache();
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/TaskKeyLruCache.java b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/TaskKeyLruCache.java
index e106c65..bc57b08 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/TaskKeyLruCache.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/TaskKeyLruCache.java
@@ -49,7 +49,7 @@
@Override
protected void entryRemoved(boolean evicted, Integer taskId, V oldV, V newV) {
- if (mEvictionCallback != null) {
+ if (mEvictionCallback != null && evicted) {
mEvictionCallback.onEntryEvicted(mKeys.get(taskId));
}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java
index 13fc702..82287873 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java
@@ -31,6 +31,7 @@
import android.app.ActivityManager;
import android.app.ActivityManager.RecentTaskInfo;
import android.app.ActivityManager.RunningTaskInfo;
+import android.app.ActivityManager.TaskSnapshot;
import android.app.ActivityOptions;
import android.app.ActivityTaskManager;
import android.app.AppGlobals;
@@ -235,9 +236,9 @@
}
@Override
- public void onAnimationCanceled(boolean deferredWithScreenshot) {
+ public void onAnimationCanceled(TaskSnapshot taskSnapshot) {
animationHandler.onAnimationCanceled(
- deferredWithScreenshot ? new ThumbnailData() : null);
+ taskSnapshot != null ? new ThumbnailData(taskSnapshot) : null);
}
};
}
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 c215d0f..7757161 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
@@ -95,6 +95,11 @@
public void onTaskDisplayChanged(int taskId, int newDisplayId) { }
/**
+ * Called when any additions or deletions to the recent tasks list have been made.
+ */
+ public void onRecentTaskListUpdated() { }
+
+ /**
* Checks that the current user matches the process. Since
* {@link android.app.ITaskStackListener} is not multi-user aware, handlers of
* {@link TaskStackChangeListener} should make this call to verify that we don't act on events
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 d570a58..a7f4396 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
@@ -213,6 +213,11 @@
mHandler.obtainMessage(H.ON_TASK_DISPLAY_CHANGED, taskId, newDisplayId).sendToTarget();
}
+ @Override
+ public void onRecentTaskListUpdated() throws RemoteException {
+ mHandler.obtainMessage(H.ON_TASK_LIST_UPDATED).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;
@@ -234,6 +239,7 @@
private static final int ON_BACK_PRESSED_ON_TASK_ROOT = 18;
private static final int ON_SINGLE_TASK_DISPLAY_DRAWN = 19;
private static final int ON_TASK_DISPLAY_CHANGED = 20;
+ private static final int ON_TASK_LIST_UPDATED = 21;
public H(Looper looper) {
@@ -382,6 +388,12 @@
}
break;
}
+ case ON_TASK_LIST_UPDATED: {
+ for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
+ mTaskStackListeners.get(i).onRecentTaskListUpdated();
+ }
+ break;
+ }
}
}
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputView.java
index a4b6958..517abac 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputView.java
@@ -253,6 +253,7 @@
protected void onUserInput() {
if (mCallback != null) {
mCallback.userActivity();
+ mCallback.onUserInput();
}
mSecurityMessageDisplay.setMessage("");
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java
index 55ddfc3..56b38f7 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java
@@ -274,6 +274,7 @@
@Override
public void onPatternCellAdded(List<LockPatternView.Cell> pattern) {
mCallback.userActivity();
+ mCallback.onUserInput();
}
@Override
@@ -336,6 +337,7 @@
});
if (pattern.size() > MIN_PATTERN_BEFORE_POKE_WAKELOCK) {
mCallback.userActivity();
+ mCallback.onUserInput();
}
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityCallback.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityCallback.java
index cbfbffb..49dcfff 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityCallback.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityCallback.java
@@ -55,4 +55,9 @@
default void onCancelClicked() {
// No-op
}
+
+ /**
+ * Invoked whenever users are typing their password or drawing a pattern.
+ */
+ void onUserInput();
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
index 8059dcf..169c97b 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
@@ -596,6 +596,11 @@
}
}
+ @Override
+ public void onUserInput() {
+ mUpdateMonitor.cancelFaceAuth();
+ }
+
public void dismiss(boolean authenticated, int targetId) {
mSecurityCallback.dismiss(authenticated, targetId);
}
@@ -640,6 +645,8 @@
@Override
public void dismiss(boolean securityVerified, int targetUserId) { }
@Override
+ public void onUserInput() { }
+ @Override
public void reset() {}
};
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 6a54782..de20972 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -345,7 +345,8 @@
Trace.endSection();
break;
case MSG_FACE_UNLOCK_STATE_CHANGED:
- Trace.beginSection("KeyguardUpdateMonitor#handler MSG_FACE_UNLOCK_STATE_CHANGED");
+ Trace.beginSection(
+ "KeyguardUpdateMonitor#handler MSG_FACE_UNLOCK_STATE_CHANGED");
handleFaceUnlockStateChanged(msg.arg1 != 0, msg.arg2);
Trace.endSection();
break;
@@ -395,15 +396,15 @@
private BiometricManager mBiometricManager;
private IBiometricEnabledOnKeyguardCallback mBiometricEnabledCallback =
new IBiometricEnabledOnKeyguardCallback.Stub() {
- @Override
- public void onChanged(BiometricSourceType type, boolean enabled, int userId)
- throws RemoteException {
- if (type == BiometricSourceType.FACE) {
- mFaceSettingEnabledForUser.put(userId, enabled);
- updateFaceListeningState();
- }
- }
- };
+ @Override
+ public void onChanged(BiometricSourceType type, boolean enabled, int userId)
+ throws RemoteException {
+ if (type == BiometricSourceType.FACE) {
+ mFaceSettingEnabledForUser.put(userId, enabled);
+ updateFaceListeningState();
+ }
+ }
+ };
private PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
@Override
@@ -414,11 +415,11 @@
private OnSubscriptionsChangedListener mSubscriptionListener =
new OnSubscriptionsChangedListener() {
- @Override
- public void onSubscriptionsChanged() {
- mHandler.sendEmptyMessage(MSG_SIM_SUBSCRIPTION_INFO_CHANGED);
- }
- };
+ @Override
+ public void onSubscriptionsChanged() {
+ mHandler.sendEmptyMessage(MSG_SIM_SUBSCRIPTION_INFO_CHANGED);
+ }
+ };
private SparseBooleanArray mUserHasTrust = new SparseBooleanArray();
private SparseBooleanArray mUserTrustIsManaged = new SparseBooleanArray();
@@ -459,6 +460,7 @@
}
private void handleSimSubscriptionInfoChanged() {
+ checkIsHandlerThread();
if (DEBUG_SIM_STATES) {
Log.v(TAG, "onSubscriptionInfoChanged()");
List<SubscriptionInfo> sil = mSubscriptionManager.getActiveSubscriptionInfoList(false);
@@ -492,17 +494,17 @@
}
}
}
- for (int j = 0; j < mCallbacks.size(); j++) {
- KeyguardUpdateMonitorCallback cb = mCallbacks.get(j).get();
- if (cb != null) {
- cb.onRefreshCarrierInfo();
- }
- }
+ callbacksRefreshCarrierInfo();
}
private void handleAirplaneModeChanged() {
- for (int j = 0; j < mCallbacks.size(); j++) {
- KeyguardUpdateMonitorCallback cb = mCallbacks.get(j).get();
+ callbacksRefreshCarrierInfo();
+ }
+
+ private void callbacksRefreshCarrierInfo() {
+ checkIsHandlerThread();
+ for (int i = 0; i < mCallbacks.size(); i++) {
+ KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
if (cb != null) {
cb.onRefreshCarrierInfo();
}
@@ -528,7 +530,6 @@
public void onTrustManagedChanged(boolean managed, int userId) {
checkIsHandlerThread();
mUserTrustIsManaged.put(userId, managed);
-
for (int i = 0; i < mCallbacks.size(); i++) {
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
if (cb != null) {
@@ -539,7 +540,6 @@
/**
* Updates KeyguardUpdateMonitor's internal state to know if keyguard is goingAway
- * @param goingAway
*/
public void setKeyguardGoingAway(boolean goingAway) {
mKeyguardGoingAway = goingAway;
@@ -548,7 +548,6 @@
/**
* Updates KeyguardUpdateMonitor's internal state to know if keyguard is occluded
- * @param occluded
*/
public void setKeyguardOccluded(boolean occluded) {
mKeyguardOccluded = occluded;
@@ -585,6 +584,7 @@
@VisibleForTesting
protected void onFingerprintAuthenticated(int userId) {
+ checkIsHandlerThread();
Trace.beginSection("KeyGuardUpdateMonitor#onFingerPrintAuthenticated");
mUserFingerprintAuthenticated.put(userId, true);
// Update/refresh trust state only if user can skip bouncer
@@ -610,6 +610,7 @@
}
private void handleFingerprintAuthFailed() {
+ checkIsHandlerThread();
for (int i = 0; i < mCallbacks.size(); i++) {
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
if (cb != null) {
@@ -621,6 +622,7 @@
}
private void handleFingerprintAcquired(int acquireInfo) {
+ checkIsHandlerThread();
if (acquireInfo != FingerprintManager.FINGERPRINT_ACQUIRED_GOOD) {
return;
}
@@ -658,6 +660,7 @@
}
private void handleFingerprintHelp(int msgId, String helpString) {
+ checkIsHandlerThread();
for (int i = 0; i < mCallbacks.size(); i++) {
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
if (cb != null) {
@@ -676,6 +679,7 @@
};
private void handleFingerprintError(int msgId, String errString) {
+ checkIsHandlerThread();
if (msgId == FingerprintManager.FINGERPRINT_ERROR_CANCELED && mHandler.hasCallbacks(
mCancelNotReceived)) {
mHandler.removeCallbacks(mCancelNotReceived);
@@ -741,6 +745,7 @@
@VisibleForTesting
protected void onFaceAuthenticated(int userId) {
Trace.beginSection("KeyGuardUpdateMonitor#onFaceAuthenticated");
+ checkIsHandlerThread();
mUserFaceAuthenticated.put(userId, true);
// Update/refresh trust state only if user can skip bouncer
if (getUserCanSkipBouncer(userId)) {
@@ -766,6 +771,7 @@
}
private void handleFaceAuthFailed() {
+ checkIsHandlerThread();
setFaceRunningState(BIOMETRIC_STATE_STOPPED);
for (int i = 0; i < mCallbacks.size(); i++) {
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
@@ -778,6 +784,7 @@
}
private void handleFaceAcquired(int acquireInfo) {
+ checkIsHandlerThread();
if (acquireInfo != FaceManager.FACE_ACQUIRED_GOOD) {
return;
}
@@ -821,6 +828,7 @@
}
private void handleFaceHelp(int msgId, String helpString) {
+ checkIsHandlerThread();
if (DEBUG_FACE) Log.d(TAG, "Face help received: " + helpString);
for (int i = 0; i < mCallbacks.size(); i++) {
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
@@ -840,6 +848,7 @@
};
private void handleFaceError(int msgId, String errString) {
+ checkIsHandlerThread();
if (DEBUG_FACE) Log.d(TAG, "Face error received: " + errString);
if (msgId == FaceManager.FACE_ERROR_CANCELED && mHandler.hasCallbacks(mCancelNotReceived)) {
mHandler.removeCallbacks(mCancelNotReceived);
@@ -894,6 +903,7 @@
}
private void notifyFaceRunningStateChanged() {
+ checkIsHandlerThread();
for (int i = 0; i < mCallbacks.size(); i++) {
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
if (cb != null) {
@@ -938,7 +948,7 @@
final DevicePolicyManager dpm =
(DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
return dpm != null && (dpm.getKeyguardDisabledFeatures(null, userId)
- & DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT) != 0
+ & DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT) != 0
|| isSimPinSecure();
}
@@ -1013,6 +1023,7 @@
}
private void dispatchErrorMessage(CharSequence message) {
+ checkIsHandlerThread();
for (int i = 0; i < mCallbacks.size(); i++) {
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
if (cb != null) {
@@ -1092,8 +1103,9 @@
}
if (DEBUG_SIM_STATES) {
Log.v(TAG, "action " + action
- + " state: " + intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE)
- + " slotId: " + args.slotId + " subid: " + args.subId);
+ + " state: " + intent.getStringExtra(
+ IccCardConstants.INTENT_KEY_ICC_STATE)
+ + " slotId: " + args.slotId + " subid: " + args.subId);
}
mHandler.obtainMessage(MSG_SIM_STATE_CHANGE, args.subId, args.slotId, args.simState)
.sendToTarget();
@@ -1138,7 +1150,9 @@
mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_INFO_CHANGED,
intent.getIntExtra(Intent.EXTRA_USER_HANDLE, getSendingUserId()), 0));
} else if (ACTION_FACE_UNLOCK_STARTED.equals(action)) {
- Trace.beginSection("KeyguardUpdateMonitor.mBroadcastAllReceiver#onReceive ACTION_FACE_UNLOCK_STARTED");
+ Trace.beginSection(
+ "KeyguardUpdateMonitor.mBroadcastAllReceiver#onReceive "
+ + "ACTION_FACE_UNLOCK_STARTED");
mHandler.sendMessage(mHandler.obtainMessage(MSG_FACE_UNLOCK_STATE_CHANGED, 1,
getSendingUserId()));
Trace.endSection();
@@ -1267,7 +1281,7 @@
SubscriptionManager.INVALID_SUBSCRIPTION_ID);
if (IccCardConstants.INTENT_VALUE_ICC_ABSENT.equals(stateExtra)) {
final String absentReason = intent
- .getStringExtra(IccCardConstants.INTENT_KEY_LOCKED_REASON);
+ .getStringExtra(IccCardConstants.INTENT_KEY_LOCKED_REASON);
if (IccCardConstants.INTENT_VALUE_ABSENT_ON_PERM_DISABLED.equals(
absentReason)) {
@@ -1292,7 +1306,7 @@
} else if (IccCardConstants.INTENT_VALUE_ICC_CARD_IO_ERROR.equals(stateExtra)) {
state = IccCardConstants.State.CARD_IO_ERROR;
} else if (IccCardConstants.INTENT_VALUE_ICC_LOADED.equals(stateExtra)
- || IccCardConstants.INTENT_VALUE_ICC_IMSI.equals(stateExtra)) {
+ || IccCardConstants.INTENT_VALUE_ICC_IMSI.equals(stateExtra)) {
// This is required because telephony doesn't return to "READY" after
// these state transitions. See bug 7197471.
state = IccCardConstants.State.READY;
@@ -1319,6 +1333,7 @@
public final int plugged;
public final int health;
public final int maxChargingWattage;
+
public BatteryStatus(int status, int level, int plugged, int health,
int maxChargingWattage) {
this.status = status;
@@ -1330,6 +1345,7 @@
/**
* Determine whether the device is plugged in (USB, power, or wireless).
+ *
* @return true if the device is plugged in.
*/
public boolean isPluggedIn() {
@@ -1340,6 +1356,7 @@
/**
* Determine whether the device is plugged in (USB, power).
+ *
* @return true if the device is plugged in wired (as opposed to wireless)
*/
public boolean isPluggedInWired() {
@@ -1351,6 +1368,7 @@
* Whether or not the device is charged. Note that some devices never return 100% for
* battery level, so this allows either battery level or status to determine if the
* battery is charged.
+ *
* @return true if the device is charged
*/
public boolean isCharged() {
@@ -1359,6 +1377,7 @@
/**
* Whether battery is low and needs to be charged.
+ *
* @return true if battery is low
*/
public boolean isBatteryLow() {
@@ -1368,8 +1387,8 @@
public final int getChargingSpeed(int slowThreshold, int fastThreshold) {
return maxChargingWattage <= 0 ? CHARGING_UNKNOWN :
maxChargingWattage < slowThreshold ? CHARGING_SLOWLY :
- maxChargingWattage > fastThreshold ? CHARGING_FAST :
- CHARGING_REGULAR;
+ maxChargingWattage > fastThreshold ? CHARGING_FAST :
+ CHARGING_REGULAR;
}
@Override
@@ -1414,9 +1433,9 @@
protected void handleStartedWakingUp() {
Trace.beginSection("KeyguardUpdateMonitor#handleStartedWakingUp");
+ checkIsHandlerThread();
updateBiometricListeningState();
- final int count = mCallbacks.size();
- for (int i = 0; i < count; i++) {
+ for (int i = 0; i < mCallbacks.size(); i++) {
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
if (cb != null) {
cb.onStartedWakingUp();
@@ -1426,9 +1445,9 @@
}
protected void handleStartedGoingToSleep(int arg1) {
+ checkIsHandlerThread();
clearBiometricRecognized();
- final int count = mCallbacks.size();
- for (int i = 0; i < count; i++) {
+ for (int i = 0; i < mCallbacks.size(); i++) {
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
if (cb != null) {
cb.onStartedGoingToSleep(arg1);
@@ -1439,9 +1458,9 @@
}
protected void handleFinishedGoingToSleep(int arg1) {
+ checkIsHandlerThread();
mGoingToSleep = false;
- final int count = mCallbacks.size();
- for (int i = 0; i < count; i++) {
+ for (int i = 0; i < mCallbacks.size(); i++) {
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
if (cb != null) {
cb.onFinishedGoingToSleep(arg1);
@@ -1451,8 +1470,8 @@
}
private void handleScreenTurnedOn() {
- final int count = mCallbacks.size();
- for (int i = 0; i < count; i++) {
+ checkIsHandlerThread();
+ for (int i = 0; i < mCallbacks.size(); i++) {
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
if (cb != null) {
cb.onScreenTurnedOn();
@@ -1461,11 +1480,11 @@
}
private void handleScreenTurnedOff() {
+ checkIsHandlerThread();
mLockIconPressed = false;
mHardwareFingerprintUnavailableRetryCount = 0;
mHardwareFaceUnavailableRetryCount = 0;
- final int count = mCallbacks.size();
- for (int i = 0; i < count; i++) {
+ for (int i = 0; i < mCallbacks.size(); i++) {
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
if (cb != null) {
cb.onScreenTurnedOff();
@@ -1474,9 +1493,9 @@
}
private void handleDreamingStateChanged(int dreamStart) {
- final int count = mCallbacks.size();
+ checkIsHandlerThread();
mIsDreaming = dreamStart == 1;
- for (int i = 0; i < count; i++) {
+ for (int i = 0; i < mCallbacks.size(); i++) {
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
if (cb != null) {
cb.onDreamingStateChanged(mIsDreaming);
@@ -1486,6 +1505,7 @@
}
private void handleUserInfoChanged(int userId) {
+ checkIsHandlerThread();
for (int i = 0; i < mCallbacks.size(); i++) {
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
if (cb != null) {
@@ -1495,6 +1515,7 @@
}
private void handleUserUnlocked() {
+ checkIsHandlerThread();
mNeedsSlowUnlockTransition = resolveNeedsSlowUnlockTransition();
for (int i = 0; i < mCallbacks.size(); i++) {
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
@@ -1559,6 +1580,7 @@
mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_SWITCHING,
newUserId, 0, reply));
}
+
@Override
public void onUserSwitchComplete(int newUserId) throws RemoteException {
mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_SWITCH_COMPLETE,
@@ -1644,6 +1666,7 @@
/**
* Called whenever passive authentication is requested or aborted by a sensor.
+ *
* @param active If the interrupt started or ended.
*/
public void onAuthInterruptDetected(boolean active) {
@@ -1664,6 +1687,13 @@
updateFaceListeningState();
}
+ /**
+ * In case face auth is running, cancel it.
+ */
+ public void cancelFaceAuth() {
+ stopListeningForFace();
+ }
+
private void updateFaceListeningState() {
// If this message exists, we should not authenticate again until this message is
// consumed by the handler
@@ -1891,7 +1921,7 @@
checkIsHandlerThread();
if (hasLockscreenWallpaper != mHasLockscreenWallpaper) {
mHasLockscreenWallpaper = hasLockscreenWallpaper;
- for (int i = mCallbacks.size() - 1; i >= 0; i--) {
+ for (int i = 0; i < mCallbacks.size(); i++) {
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
if (cb != null) {
cb.onHasLockscreenWallpaperChanged(hasLockscreenWallpaper);
@@ -1911,8 +1941,9 @@
* Handle {@link #MSG_DPM_STATE_CHANGED}
*/
private void handleDevicePolicyManagerStateChanged() {
+ checkIsHandlerThread();
updateFingerprintListeningState();
- for (int i = mCallbacks.size() - 1; i >= 0; i--) {
+ for (int i = 0; i < mCallbacks.size(); i++) {
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
if (cb != null) {
cb.onDevicePolicyManagerStateChanged();
@@ -1924,6 +1955,7 @@
* Handle {@link #MSG_USER_SWITCHING}
*/
private void handleUserSwitching(int userId, IRemoteCallback reply) {
+ checkIsHandlerThread();
for (int i = 0; i < mCallbacks.size(); i++) {
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
if (cb != null) {
@@ -1940,6 +1972,7 @@
* Handle {@link #MSG_USER_SWITCH_COMPLETE}
*/
private void handleUserSwitchComplete(int userId) {
+ checkIsHandlerThread();
for (int i = 0; i < mCallbacks.size(); i++) {
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
if (cb != null) {
@@ -1962,6 +1995,7 @@
* Handle {@link #MSG_BOOT_COMPLETED}
*/
private void handleBootCompleted() {
+ checkIsHandlerThread();
if (mBootCompleted) return;
mBootCompleted = true;
for (int i = 0; i < mCallbacks.size(); i++) {
@@ -1984,6 +2018,7 @@
* Handle {@link #MSG_DEVICE_PROVISIONED}
*/
private void handleDeviceProvisioned() {
+ checkIsHandlerThread();
for (int i = 0; i < mCallbacks.size(); i++) {
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
if (cb != null) {
@@ -2001,6 +2036,7 @@
* Handle {@link #MSG_PHONE_STATE_CHANGED}
*/
private void handlePhoneStateChanged(String newState) {
+ checkIsHandlerThread();
if (DEBUG) Log.d(TAG, "handlePhoneStateChanged(" + newState + ")");
if (TelephonyManager.EXTRA_STATE_IDLE.equals(newState)) {
mPhoneState = TelephonyManager.CALL_STATE_IDLE;
@@ -2021,6 +2057,7 @@
* Handle {@link #MSG_RINGER_MODE_CHANGED}
*/
private void handleRingerModeChange(int mode) {
+ checkIsHandlerThread();
if (DEBUG) Log.d(TAG, "handleRingerModeChange(" + mode + ")");
mRingMode = mode;
for (int i = 0; i < mCallbacks.size(); i++) {
@@ -2035,6 +2072,7 @@
* Handle {@link #MSG_TIME_UPDATE}
*/
private void handleTimeUpdate() {
+ checkIsHandlerThread();
if (DEBUG) Log.d(TAG, "handleTimeUpdate");
for (int i = 0; i < mCallbacks.size(); i++) {
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
@@ -2048,6 +2086,7 @@
* Handle (@line #MSG_TIMEZONE_UPDATE}
*/
private void handleTimeZoneUpdate(String timeZone) {
+ checkIsHandlerThread();
if (DEBUG) Log.d(TAG, "handleTimeZoneUpdate");
for (int i = 0; i < mCallbacks.size(); i++) {
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
@@ -2063,6 +2102,7 @@
* Handle {@link #MSG_BATTERY_UPDATE}
*/
private void handleBatteryUpdate(BatteryStatus status) {
+ checkIsHandlerThread();
if (DEBUG) Log.d(TAG, "handleBatteryUpdate");
final boolean batteryUpdateInteresting = isBatteryUpdateInteresting(mBatteryStatus, status);
mBatteryStatus = status;
@@ -2080,13 +2120,14 @@
* Handle Telephony status during Boot for CarrierText display policy
*/
@VisibleForTesting
- void updateTelephonyCapable(boolean capable){
+ void updateTelephonyCapable(boolean capable) {
+ checkIsHandlerThread();
if (capable == mTelephonyCapable) {
return;
}
mTelephonyCapable = capable;
- for (WeakReference<KeyguardUpdateMonitorCallback> ref : mCallbacks) {
- KeyguardUpdateMonitorCallback cb = ref.get();
+ for (int i = 0; i < mCallbacks.size(); i++) {
+ KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
if (cb != null) {
cb.onTelephonyCapable(mTelephonyCapable);
}
@@ -2101,7 +2142,7 @@
checkIsHandlerThread();
if (DEBUG_SIM_STATES) {
Log.d(TAG, "handleSimStateChange(subId=" + subId + ", slotId="
- + slotId + ", state=" + state +")");
+ + slotId + ", state=" + state + ")");
}
boolean becameAbsent = false;
@@ -2169,12 +2210,7 @@
mServiceStates.put(subId, serviceState);
- for (int j = 0; j < mCallbacks.size(); j++) {
- KeyguardUpdateMonitorCallback cb = mCallbacks.get(j).get();
- if (cb != null) {
- cb.onRefreshCarrierInfo();
- }
- }
+ callbacksRefreshCarrierInfo();
}
public boolean isKeyguardVisible() {
@@ -2226,9 +2262,11 @@
/**
* Handle {@link #MSG_KEYGUARD_BOUNCER_CHANGED}
+ *
* @see #sendKeyguardBouncerChanged(boolean)
*/
private void handleKeyguardBouncerChanged(int bouncer) {
+ checkIsHandlerThread();
if (DEBUG) Log.d(TAG, "handleKeyguardBouncerChanged(" + bouncer + ")");
boolean isBouncer = (bouncer == 1);
mBouncer = isBouncer;
@@ -2254,6 +2292,7 @@
* Handle {@link #MSG_REPORT_EMERGENCY_CALL_ACTION}
*/
private void handleReportEmergencyCallAction() {
+ checkIsHandlerThread();
for (int i = 0; i < mCallbacks.size(); i++) {
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
if (cb != null) {
@@ -2266,7 +2305,7 @@
final boolean nowPluggedIn = current.isPluggedIn();
final boolean wasPluggedIn = old.isPluggedIn();
final boolean stateChangedWhilePluggedIn = wasPluggedIn && nowPluggedIn
- && (old.status != current.status);
+ && (old.status != current.status);
// change in plug state is always interesting
if (wasPluggedIn != nowPluggedIn || stateChangedWhilePluggedIn) {
@@ -2293,31 +2332,34 @@
*/
public void removeCallback(KeyguardUpdateMonitorCallback callback) {
checkIsHandlerThread();
- if (DEBUG) Log.v(TAG, "*** unregister callback for " + callback);
- for (int i = mCallbacks.size() - 1; i >= 0; i--) {
- if (mCallbacks.get(i).get() == callback) {
- mCallbacks.remove(i);
- }
+ if (DEBUG) {
+ Log.v(TAG, "*** unregister callback for " + callback);
}
+
+ mCallbacks.removeIf(el -> el.get() == callback);
}
/**
* Register to receive notifications about general keyguard information
* (see {@link InfoCallback}.
+ *
* @param callback The callback to register
*/
public void registerCallback(KeyguardUpdateMonitorCallback callback) {
checkIsHandlerThread();
if (DEBUG) Log.v(TAG, "*** register callback for " + callback);
// Prevent adding duplicate callbacks
+
for (int i = 0; i < mCallbacks.size(); i++) {
if (mCallbacks.get(i).get() == callback) {
- if (DEBUG) Log.e(TAG, "Object tried to add another callback",
- new Exception("Called by"));
+ if (DEBUG) {
+ Log.e(TAG, "Object tried to add another callback",
+ new Exception("Called by"));
+ }
return;
}
}
- mCallbacks.add(new WeakReference<KeyguardUpdateMonitorCallback>(callback));
+ mCallbacks.add(new WeakReference<>(callback));
removeCallback(null); // remove unused references
sendUpdates(callback);
}
@@ -2388,7 +2430,7 @@
*
* @param bypassHandler runs immediately.
*
- * NOTE: Must be called from UI thread if bypassHandler == true.
+ * NOTE: Must be called from UI thread if bypassHandler == true.
*/
public void reportEmergencyCallAction(boolean bypassHandler) {
if (!bypassHandler) {
@@ -2401,7 +2443,7 @@
/**
* @return Whether the device is provisioned (whether they have gone through
- * the setup wizard)
+ * the setup wizard)
*/
public boolean isDeviceProvisioned() {
return mDeviceProvisioned;
@@ -2412,6 +2454,7 @@
}
public void clearBiometricRecognized() {
+ checkIsHandlerThread();
mUserFingerprintAuthenticated.clear();
mUserFaceAuthenticated.clear();
mTrustManager.clearAllBiometricRecognized(BiometricSourceType.FINGERPRINT);
@@ -2432,6 +2475,7 @@
/**
* If any SIM cards are currently secure.
+ *
* @see #isSimPinSecure(State)
*/
public boolean isSimPinSecure() {
@@ -2478,11 +2522,11 @@
// 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);
+ int simState = tele.getSimState(slotId);
State state;
try {
state = State.intToState(simState);
- } catch(IllegalArgumentException ex) {
+ } catch (IllegalArgumentException ex) {
Log.w(TAG, "Unknown sim state: " + simState);
state = State.UNKNOWN;
}
@@ -2526,7 +2570,7 @@
}
public void dispatchFinishedGoingToSleep(int why) {
- synchronized(this) {
+ synchronized (this) {
mDeviceInteractive = false;
}
mHandler.sendMessage(mHandler.obtainMessage(MSG_FINISHED_GOING_TO_SLEEP, why, 0));
@@ -2540,7 +2584,7 @@
}
public void dispatchScreenTurnedOff() {
- synchronized(this) {
+ synchronized (this) {
mScreenOn = false;
}
mHandler.sendEmptyMessage(MSG_SCREEN_TURNED_OFF);
@@ -2564,7 +2608,7 @@
/**
* Find the next SubscriptionId for a SIM in the given state, favoring lower slot numbers first.
- * @param state
+ *
* @return subid or {@link SubscriptionManager#INVALID_SUBSCRIPTION_ID} if none found
*/
public int getNextSubIdForState(State state) {
@@ -2575,7 +2619,7 @@
final SubscriptionInfo info = list.get(i);
final int id = info.getSubscriptionId();
int slotId = SubscriptionManager.getSlotIndex(id);
- if (state == getSimState(id) && bestSlotId > slotId ) {
+ if (state == getSimState(id) && bestSlotId > slotId) {
resultId = id;
bestSlotId = slotId;
}
@@ -2604,6 +2648,7 @@
boolean logoutEnabled = mDevicePolicyManager.isLogoutEnabled();
if (mLogoutEnabled != logoutEnabled) {
mLogoutEnabled = logoutEnabled;
+
for (int i = 0; i < mCallbacks.size(); i++) {
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
if (cb != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
index 311ed8a..7e3b423 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
@@ -66,6 +66,7 @@
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
import com.android.systemui.statusbar.phone.UnlockMethodCache;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
+import com.android.systemui.statusbar.policy.KeyguardMonitor;
import com.android.systemui.util.AsyncSensorManager;
import com.android.systemui.volume.VolumeDialogComponent;
@@ -150,9 +151,9 @@
LockscreenWallpaper lockscreenWallpaper,
TriConsumer<ScrimState, Float, GradientColors> scrimStateListener,
Consumer<Integer> scrimVisibleListener, DozeParameters dozeParameters,
- AlarmManager alarmManager) {
+ AlarmManager alarmManager, KeyguardMonitor keyguardMonitor) {
return new ScrimController(scrimBehind, scrimInFront, scrimStateListener,
- scrimVisibleListener, dozeParameters, alarmManager);
+ scrimVisibleListener, dozeParameters, alarmManager, keyguardMonitor);
}
public NotificationIconAreaController createNotificationIconAreaController(Context context,
diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
index 4a4fead..cf9c470 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
@@ -339,7 +339,7 @@
intent.setComponent(assistComponent);
intent.putExtras(args);
- if (structureEnabled) {
+ if (structureEnabled && AssistUtils.isDisclosureEnabled(mContext)) {
showDisclosure();
}
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
index 923ca20..de08a8c 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
@@ -182,7 +182,7 @@
mActivityView = new ActivityView(mContext, null /* attrs */, 0 /* defStyle */,
true /* singleTaskInstance */);
-
+ // Set ActivityView's alpha value as zero, since there is no view content to be shown.
setContentVisibility(false);
addView(mActivityView);
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java
index 128cc61..ee79e6b 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java
@@ -26,6 +26,7 @@
import android.view.MotionEvent;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.Dependency;
import com.android.systemui.classifier.brightline.BrightLineFalsingManager;
import com.android.systemui.classifier.brightline.FalsingDataProvider;
@@ -102,7 +103,8 @@
} else {
mInternalFalsingManager = new BrightLineFalsingManager(
new FalsingDataProvider(context.getResources().getDisplayMetrics()),
- Dependency.get(AsyncSensorManager.class)
+ Dependency.get(AsyncSensorManager.class),
+ KeyguardUpdateMonitor.getInstance(context)
);
}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/brightline/BrightLineFalsingManager.java b/packages/SystemUI/src/com/android/systemui/classifier/brightline/BrightLineFalsingManager.java
index ce82bbf..9e0b702 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/brightline/BrightLineFalsingManager.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/brightline/BrightLineFalsingManager.java
@@ -23,11 +23,14 @@
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
+import android.hardware.biometrics.BiometricSourceType;
import android.net.Uri;
import android.util.Log;
import android.view.MotionEvent;
import com.android.internal.logging.MetricsLogger;
+import com.android.keyguard.KeyguardUpdateMonitor;
+import com.android.keyguard.KeyguardUpdateMonitorCallback;
import com.android.systemui.classifier.Classifier;
import com.android.systemui.plugins.FalsingManager;
@@ -47,11 +50,13 @@
private final SensorManager mSensorManager;
private final FalsingDataProvider mDataProvider;
+ private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
private boolean mSessionStarted;
private MetricsLogger mMetricsLogger;
private int mIsFalseTouchCalls;
private boolean mShowingAod;
private boolean mScreenOn;
+ private boolean mJustUnlockedWithFace;
private final ExecutorService mBackgroundExecutor = Executors.newSingleThreadExecutor();
@@ -68,10 +73,27 @@
}
};
- public BrightLineFalsingManager(FalsingDataProvider falsingDataProvider,
- SensorManager sensorManager) {
+ private final KeyguardUpdateMonitorCallback mKeyguardUpdateCallback =
+ new KeyguardUpdateMonitorCallback() {
+ @Override
+ public void onBiometricAuthenticated(int userId,
+ BiometricSourceType biometricSourceType) {
+ if (userId == KeyguardUpdateMonitor.getCurrentUser()
+ && biometricSourceType == BiometricSourceType.FACE) {
+ mJustUnlockedWithFace = true;
+ }
+ }
+ };
+
+ public BrightLineFalsingManager(
+ FalsingDataProvider falsingDataProvider,
+ SensorManager sensorManager,
+ KeyguardUpdateMonitor keyguardUpdateMonitor) {
+ mKeyguardUpdateMonitor = keyguardUpdateMonitor;
mDataProvider = falsingDataProvider;
mSensorManager = sensorManager;
+ mKeyguardUpdateMonitor.registerCallback(mKeyguardUpdateCallback);
+
mMetricsLogger = new MetricsLogger();
mClassifiers = new ArrayList<>();
DistanceClassifier distanceClassifier = new DistanceClassifier(mDataProvider);
@@ -110,6 +132,7 @@
if (!mSessionStarted && !mShowingAod && mScreenOn) {
logDebug("Starting Session");
mSessionStarted = true;
+ mJustUnlockedWithFace = false;
registerSensors();
mClassifiers.forEach(FalsingClassifier::onSessionStarted);
}
@@ -141,7 +164,7 @@
@Override
public boolean isFalseTouch() {
- boolean r = mClassifiers.stream().anyMatch(falsingClassifier -> {
+ boolean r = !mJustUnlockedWithFace && mClassifiers.stream().anyMatch(falsingClassifier -> {
boolean result = falsingClassifier.isFalseTouch();
if (result) {
logInfo(falsingClassifier.getClass().getName() + ": true");
@@ -335,6 +358,7 @@
@Override
public void cleanup() {
unregisterSensors();
+ mKeyguardUpdateMonitor.removeCallback(mKeyguardUpdateCallback);
}
static void logDebug(String msg) {
diff --git a/packages/SystemUI/src/com/android/systemui/colorextraction/SysuiColorExtractor.java b/packages/SystemUI/src/com/android/systemui/colorextraction/SysuiColorExtractor.java
index d3e8b3d..3ca1f59 100644
--- a/packages/SystemUI/src/com/android/systemui/colorextraction/SysuiColorExtractor.java
+++ b/packages/SystemUI/src/com/android/systemui/colorextraction/SysuiColorExtractor.java
@@ -68,9 +68,11 @@
mBackdropColors.setMainColor(Color.BLACK);
// Listen to all users instead of only the current one.
- wallpaperManager.removeOnColorsChangedListener(this);
- wallpaperManager.addOnColorsChangedListener(this, null /* handler */,
- UserHandle.USER_ALL);
+ if (wallpaperManager.isWallpaperSupported()) {
+ wallpaperManager.removeOnColorsChangedListener(this);
+ wallpaperManager.addOnColorsChangedListener(this, null /* handler */,
+ UserHandle.USER_ALL);
+ }
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
index f6a921d..f79bb3a 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
@@ -107,8 +107,7 @@
config.dozePickupSensorAvailable(),
DozeLog.REASON_SENSOR_PICKUP, false /* touchCoords */,
false /* touchscreen */,
- false /* ignoresSetting */,
- mDozeParameters.getPickupPerformsProxCheck()),
+ false /* ignoresSetting */),
new TriggerSensor(
findSensorWithType(config.doubleTapSensorType()),
Settings.Secure.DOZE_DOUBLE_TAP_GESTURE,
@@ -205,11 +204,8 @@
public void updateListening() {
boolean anyListening = false;
for (TriggerSensor s : mSensors) {
- // We don't want to be listening while we're PAUSED (prox sensor is covered)
- // except when the sensor is already gated by prox.
- boolean listen = mListening && (!mPaused || s.performsProxCheck());
- s.setListening(listen);
- if (listen) {
+ s.setListening(mListening);
+ if (mListening) {
anyListening = true;
}
}
@@ -384,7 +380,6 @@
private final boolean mReportsTouchCoordinates;
private final boolean mSettingDefault;
private final boolean mRequiresTouchscreen;
- private final boolean mSensorPerformsProxCheck;
protected boolean mRequested;
protected boolean mRegistered;
@@ -401,14 +396,12 @@
boolean configured, int pulseReason, boolean reportsTouchCoordinates,
boolean requiresTouchscreen) {
this(sensor, setting, settingDef, configured, pulseReason, reportsTouchCoordinates,
- requiresTouchscreen, false /* ignoresSetting */,
- false /* sensorPerformsProxCheck */);
+ requiresTouchscreen, false /* ignoresSetting */);
}
private TriggerSensor(Sensor sensor, String setting, boolean settingDef,
boolean configured, int pulseReason, boolean reportsTouchCoordinates,
- boolean requiresTouchscreen, boolean ignoresSetting,
- boolean sensorPerformsProxCheck) {
+ boolean requiresTouchscreen, boolean ignoresSetting) {
mSensor = sensor;
mSetting = setting;
mSettingDefault = settingDef;
@@ -417,7 +410,6 @@
mReportsTouchCoordinates = reportsTouchCoordinates;
mRequiresTouchscreen = requiresTouchscreen;
mIgnoresSetting = ignoresSetting;
- mSensorPerformsProxCheck = sensorPerformsProxCheck;
}
public void setListening(boolean listen) {
@@ -491,23 +483,13 @@
screenX = event.values[0];
screenY = event.values[1];
}
- mCallback.onSensorPulse(mPulseReason, mSensorPerformsProxCheck, screenX, screenY,
- event.values);
+ mCallback.onSensorPulse(mPulseReason, screenX, screenY, event.values);
if (!mRegistered) {
updateListening(); // reregister, this sensor only fires once
}
}));
}
- /**
- * If the sensor itself performs proximity checks, to avoid pocket dialing.
- * Gated sensors don't need to be stopped when the {@link DozeMachine} is
- * {@link DozeMachine.State#DOZE_AOD_PAUSED}.
- */
- public boolean performsProxCheck() {
- return mSensorPerformsProxCheck;
- }
-
public void registerSettingsObserver(ContentObserver settingsObserver) {
if (mConfigured && !TextUtils.isEmpty(mSetting)) {
mResolver.registerContentObserver(
@@ -603,8 +585,7 @@
return;
}
if (DEBUG) Log.d(TAG, "onSensorEvent: " + triggerEventToString(event));
- mCallback.onSensorPulse(mPulseReason, true /* sensorPerformsProxCheck */, -1, -1,
- event.getValues());
+ mCallback.onSensorPulse(mPulseReason, -1, -1, event.getValues());
}));
}
}
@@ -614,13 +595,11 @@
/**
* Called when a sensor requests a pulse
* @param pulseReason Requesting sensor, e.g. {@link DozeLog#REASON_SENSOR_PICKUP}
- * @param sensorPerformedProxCheck true if the sensor already checked for FAR proximity.
* @param screenX the location on the screen where the sensor fired or -1
- * if the sensor doesn't support reporting screen locations.
+ * if the sensor doesn't support reporting screen locations.
* @param screenY the location on the screen where the sensor fired or -1
* @param rawValues raw values array from the event.
*/
- void onSensorPulse(int pulseReason, boolean sensorPerformedProxCheck,
- float screenX, float screenY, float[] rawValues);
+ void onSensorPulse(int pulseReason, float screenX, float screenY, float[] rawValues);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
index 310f04a..00bfb3f 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
@@ -41,6 +41,7 @@
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.util.Preconditions;
import com.android.systemui.Dependency;
+import com.android.systemui.R;
import com.android.systemui.dock.DockManager;
import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.util.Assert;
@@ -156,8 +157,7 @@
}
@VisibleForTesting
- void onSensor(int pulseReason, boolean sensorPerformedProxCheck,
- float screenX, float screenY, float[] rawValues) {
+ void onSensor(int pulseReason, float screenX, float screenY, float[] rawValues) {
boolean isDoubleTap = pulseReason == DozeLog.REASON_SENSOR_DOUBLE_TAP;
boolean isTap = pulseReason == DozeLog.REASON_SENSOR_TAP;
boolean isPickup = pulseReason == DozeLog.REASON_SENSOR_PICKUP;
@@ -169,10 +169,11 @@
if (isWakeDisplay) {
onWakeScreen(wakeEvent, mMachine.isExecutingTransition() ? null : mMachine.getState());
} else if (isLongPress) {
- requestPulse(pulseReason, sensorPerformedProxCheck, null /* onPulseSupressedListener */);
+ requestPulse(pulseReason, true /* alreadyPerformedProxCheck */,
+ null /* onPulseSupressedListener */);
} else if (isWakeLockScreen) {
if (wakeEvent) {
- requestPulse(pulseReason, sensorPerformedProxCheck,
+ requestPulse(pulseReason, true /* alreadyPerformedProxCheck */,
null /* onPulseSupressedListener */);
}
} else {
@@ -191,8 +192,7 @@
} else {
mDozeHost.extendPulse(pulseReason);
}
- }, sensorPerformedProxCheck
- || (mDockManager != null && mDockManager.isDocked()), pulseReason);
+ }, true /* alreadyPerformedProxCheck */, pulseReason);
}
if (isPickup) {
@@ -278,7 +278,7 @@
.setType(MetricsEvent.TYPE_OPEN)
.setSubtype(DozeLog.REASON_SENSOR_WAKE_UP));
}
- }, false /* alreadyPerformedProxCheck */, DozeLog.REASON_SENSOR_WAKE_UP);
+ }, true /* alreadyPerformedProxCheck */, DozeLog.REASON_SENSOR_WAKE_UP);
} else {
boolean paused = (state == DozeMachine.State.DOZE_AOD_PAUSED);
boolean pausing = (state == DozeMachine.State.DOZE_AOD_PAUSING);
@@ -433,7 +433,11 @@
public void check() {
Preconditions.checkState(!mFinished && !mRegistered);
- final Sensor sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
+ Sensor sensor = DozeSensors.findSensorWithType(mSensorManager,
+ mContext.getString(R.string.doze_brightness_sensor_type));
+ if (sensor == null) {
+ sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
+ }
if (sensor == null) {
if (DozeMachine.DEBUG) Log.d(TAG, "ProxCheck: No sensor found");
finishWithResult(RESULT_UNKNOWN);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
index f0413cd..be8a8fd 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
@@ -111,13 +111,25 @@
+ mQSPanel.getMeasuredHeight() + getPaddingBottom();
super.onMeasure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
-
// QSCustomizer will always be the height of the screen, but do this after
// other measuring to avoid changing the height of the QS.
mQSCustomizer.measure(widthMeasureSpec,
MeasureSpec.makeMeasureSpec(getDisplayHeight(), MeasureSpec.EXACTLY));
}
+
+ @Override
+ protected void measureChildWithMargins(View child, int parentWidthMeasureSpec, int widthUsed,
+ int parentHeightMeasureSpec, int heightUsed) {
+ // Do not measure QSPanel again when doing super.onMeasure.
+ // This prevents the pages in PagedTileLayout to be remeasured with a different (incorrect)
+ // size to the one used for determining the number of rows and then the number of pages.
+ if (child != mQSPanel) {
+ super.measureChildWithMargins(child, parentWidthMeasureSpec, widthUsed,
+ parentHeightMeasureSpec, heightUsed);
+ }
+ }
+
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
index c209b31..83b000d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
@@ -296,10 +296,13 @@
mY = y - containerLocation[1];
}
- private final Callback mKeyguardCallback = () -> {
- if (!isAttachedToWindow()) return;
- if (Dependency.get(KeyguardMonitor.class).isShowing() && !mOpening) {
- hide();
+ private final Callback mKeyguardCallback = new Callback() {
+ @Override
+ public void onKeyguardShowingChanged() {
+ if (!isAttachedToWindow()) return;
+ if (Dependency.get(KeyguardMonitor.class).isShowing() && !mOpening) {
+ hide();
+ }
}
};
diff --git a/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingService.java b/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingService.java
index 822a666..0383dee 100644
--- a/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingService.java
+++ b/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingService.java
@@ -27,32 +27,29 @@
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
+import android.graphics.Point;
import android.graphics.drawable.Icon;
import android.hardware.display.DisplayManager;
import android.hardware.display.VirtualDisplay;
import android.media.MediaRecorder;
-import android.media.ThumbnailUtils;
import android.media.projection.MediaProjection;
import android.media.projection.MediaProjectionManager;
import android.net.Uri;
-import android.os.Environment;
import android.os.IBinder;
import android.provider.MediaStore;
import android.provider.Settings;
import android.util.DisplayMetrics;
import android.util.Log;
+import android.util.Size;
import android.view.Surface;
import android.widget.Toast;
-import androidx.core.content.FileProvider;
-
import com.android.systemui.R;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.file.Files;
-import java.nio.file.Path;
import java.text.SimpleDateFormat;
import java.util.Date;
@@ -79,12 +76,10 @@
private static final String ACTION_DELETE = "com.android.systemui.screenrecord.DELETE";
private static final int TOTAL_NUM_TRACKS = 1;
- private static final String RECORD_DIR = "Captures"; // TODO: use a translatable string
private static final int VIDEO_BIT_RATE = 6000000;
private static final int VIDEO_FRAME_RATE = 30;
private static final int AUDIO_BIT_RATE = 16;
private static final int AUDIO_SAMPLE_RATE = 44100;
- private static final String FILE_PROVIDER = "com.android.systemui.fileprovider";
private MediaProjectionManager mMediaProjectionManager;
private MediaProjection mMediaProjection;
@@ -120,11 +115,11 @@
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
- Log.d(TAG, "RecordingService is starting");
if (intent == null) {
return Service.START_NOT_STICKY;
}
String action = intent.getAction();
+ Log.d(TAG, "onStartCommand " + action);
NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
@@ -160,41 +155,7 @@
case ACTION_STOP:
stopRecording();
-
- String fileName = new SimpleDateFormat("'screen-'yyyyMMdd-HHmmss'.mp4'")
- .format(new Date());
-
- ContentValues values = new ContentValues();
- values.put(MediaStore.Video.Media.DISPLAY_NAME, fileName);
- values.put(MediaStore.Video.Media.MIME_TYPE, "video/mp4");
- values.put(MediaStore.Video.Media.DATE_ADDED, System.currentTimeMillis());
- values.put(MediaStore.Video.Media.DATE_TAKEN, System.currentTimeMillis());
-
- ContentResolver resolver = getContentResolver();
- Uri collectionUri = MediaStore.Video.Media.getContentUri(
- MediaStore.VOLUME_EXTERNAL_PRIMARY);
- Uri itemUri = resolver.insert(collectionUri, values);
-
- File recordDir = new File(getExternalFilesDir(Environment.DIRECTORY_MOVIES),
- RECORD_DIR);
- recordDir.mkdirs();
- Path path = new File(recordDir, fileName).toPath();
- try {
- // Move file out of temp directory
- Files.move(mTempFile.toPath(), path);
-
- // Add to the mediastore
- OutputStream os = resolver.openOutputStream(itemUri, "w");
- Files.copy(path, os);
- os.close();
-
- Notification notification = createSaveNotification(itemUri, path);
- notificationManager.notify(NOTIFICATION_ID, notification);
- } catch (IOException e) {
- e.printStackTrace();
- Toast.makeText(this, R.string.screenrecord_delete_error, Toast.LENGTH_LONG)
- .show();
- }
+ saveRecording(notificationManager);
break;
case ACTION_PAUSE:
@@ -208,8 +169,7 @@
break;
case ACTION_SHARE:
- File shareFile = new File(intent.getStringExtra(EXTRA_PATH));
- Uri shareUri = FileProvider.getUriForFile(this, FILE_PROVIDER, shareFile);
+ Uri shareUri = Uri.parse(intent.getStringExtra(EXTRA_PATH));
Intent shareIntent = new Intent(Intent.ACTION_SEND)
.setType("video/mp4")
@@ -229,20 +189,18 @@
// Close quick shade
sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
- File file = new File(intent.getStringExtra(EXTRA_PATH));
- if (file.delete()) {
- Toast.makeText(
- this,
- R.string.screenrecord_delete_description,
- Toast.LENGTH_LONG).show();
+ ContentResolver resolver = getContentResolver();
+ Uri uri = Uri.parse(intent.getStringExtra(EXTRA_PATH));
+ resolver.delete(uri, null, null);
- // Remove notification
- notificationManager.cancel(NOTIFICATION_ID);
- } else {
- Log.e(TAG, "Error deleting screen recording!");
- Toast.makeText(this, R.string.screenrecord_delete_error, Toast.LENGTH_LONG)
- .show();
- }
+ Toast.makeText(
+ this,
+ R.string.screenrecord_delete_description,
+ Toast.LENGTH_LONG).show();
+
+ // Remove notification
+ notificationManager.cancel(NOTIFICATION_ID);
+ Log.d(TAG, "Deleted recording " + uri);
break;
}
return Service.START_STICKY;
@@ -313,6 +271,7 @@
mMediaRecorder.start();
} catch (IOException e) {
+ Log.e(TAG, "Error starting screen recording: " + e.getMessage());
e.printStackTrace();
throw new RuntimeException(e);
}
@@ -370,9 +329,7 @@
notificationManager.notify(NOTIFICATION_ID, mRecordingNotificationBuilder.build());
}
- private Notification createSaveNotification(Uri uri, Path path) {
- Log.d(TAG, "Screen recording saved to " + uri.toString() + ", " + path.toString());
-
+ private Notification createSaveNotification(Uri uri) {
Intent viewIntent = new Intent(Intent.ACTION_VIEW)
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_GRANT_READ_URI_PERMISSION)
.setDataAndType(uri, "video/mp4");
@@ -411,8 +368,15 @@
.setAutoCancel(true);
// Add thumbnail if available
- Bitmap thumbnailBitmap = ThumbnailUtils.createVideoThumbnail(path.toString(),
- MediaStore.Video.Thumbnails.MINI_KIND);
+ Bitmap thumbnailBitmap = null;
+ try {
+ ContentResolver resolver = getContentResolver();
+ Size size = Point.convert(MediaStore.ThumbnailConstants.MINI_SIZE);
+ thumbnailBitmap = resolver.loadThumbnail(uri, size, null);
+ } catch (IOException e) {
+ Log.e(TAG, "Error creating thumbnail: " + e.getMessage());
+ e.printStackTrace();
+ }
if (thumbnailBitmap != null) {
Notification.BigPictureStyle pictureStyle = new Notification.BigPictureStyle()
.bigPicture(thumbnailBitmap)
@@ -434,6 +398,38 @@
stopSelf();
}
+ private void saveRecording(NotificationManager notificationManager) {
+ String fileName = new SimpleDateFormat("'screen-'yyyyMMdd-HHmmss'.mp4'")
+ .format(new Date());
+
+ ContentValues values = new ContentValues();
+ values.put(MediaStore.Video.Media.DISPLAY_NAME, fileName);
+ values.put(MediaStore.Video.Media.MIME_TYPE, "video/mp4");
+ values.put(MediaStore.Video.Media.DATE_ADDED, System.currentTimeMillis());
+ values.put(MediaStore.Video.Media.DATE_TAKEN, System.currentTimeMillis());
+
+ ContentResolver resolver = getContentResolver();
+ Uri collectionUri = MediaStore.Video.Media.getContentUri(
+ MediaStore.VOLUME_EXTERNAL_PRIMARY);
+ Uri itemUri = resolver.insert(collectionUri, values);
+
+ try {
+ // Add to the mediastore
+ OutputStream os = resolver.openOutputStream(itemUri, "w");
+ Files.copy(mTempFile.toPath(), os);
+ os.close();
+
+ Notification notification = createSaveNotification(itemUri);
+ notificationManager.notify(NOTIFICATION_ID, notification);
+
+ mTempFile.delete();
+ } catch (IOException e) {
+ Log.e(TAG, "Error saving screen recording: " + e.getMessage());
+ Toast.makeText(this, R.string.screenrecord_delete_error, Toast.LENGTH_LONG)
+ .show();
+ }
+ }
+
private void setTapsVisible(boolean turnOn) {
int value = turnOn ? 1 : 0;
Settings.System.putInt(getApplicationContext().getContentResolver(),
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 c67512c..f3201ec 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java
@@ -54,7 +54,6 @@
import com.android.systemui.SysUiServiceProvider;
import com.android.systemui.SystemUI;
import com.android.systemui.UiOffloadThread;
-import com.android.systemui.shared.system.TaskStackChangeListener;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.policy.KeyguardMonitor;
import com.android.systemui.util.NotificationChannels;
@@ -138,15 +137,6 @@
}
};
- private final TaskStackChangeListener mTaskListener =
- new TaskStackChangeListener() {
- @Override
- public void onTaskStackChanged() {
- // Listen for changes to stacks and then check which instant apps are
- // foreground.
- updateForegroundInstantApps();
- }
- };
private void updateForegroundInstantApps() {
NotificationManager noMan = mContext.getSystemService(NotificationManager.class);
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 1ce4934..0009292 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
@@ -420,7 +420,14 @@
}
}
- Collections.sort(mSortedAndFiltered, mRankingComparator);
+ if (mSortedAndFiltered.size() == 1) {
+ // HACK: We need the comparator to run on all children in order to set the
+ // isHighPriority field. If there is only one child, then the comparison won't be run,
+ // so we have to trigger it manually. Get rid of this code as soon as possible.
+ mRankingComparator.compare(mSortedAndFiltered.get(0), mSortedAndFiltered.get(0));
+ } else {
+ Collections.sort(mSortedAndFiltered, mRankingComparator);
+ }
}
public void dump(PrintWriter pw, String indent) {
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 6e84089..65e744b 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
@@ -1208,12 +1208,12 @@
mChildrenContainer.reInflateViews(mExpandClickListener, mEntry.notification);
}
if (mGuts != null) {
- View oldGuts = mGuts;
+ NotificationGuts oldGuts = mGuts;
int index = indexOfChild(oldGuts);
removeView(oldGuts);
mGuts = (NotificationGuts) LayoutInflater.from(mContext).inflate(
R.layout.notification_guts, this, false);
- mGuts.setVisibility(oldGuts.getVisibility());
+ mGuts.setVisibility(oldGuts.isExposed() ? VISIBLE : GONE);
addView(mGuts, index);
}
View oldMenu = mMenuRow == null ? null : mMenuRow.getMenuView();
@@ -1366,7 +1366,9 @@
if (isChildInGroup()) {
mTranslationWhenRemoved += getNotificationParent().getTranslationY();
}
- mPrivateLayout.setRemoved();
+ for (NotificationContentView l : mLayouts) {
+ l.setRemoved();
+ }
}
public boolean wasChildInGroupWhenRemoved() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java
index 90f6324..0c5b27b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java
@@ -1542,6 +1542,15 @@
if (mHeadsUpRemoteInput != null) {
mHeadsUpRemoteInput.setRemoved();
}
+ if (mExpandedWrapper != null) {
+ mExpandedWrapper.setRemoved();
+ }
+ if (mContractedWrapper != null) {
+ mContractedWrapper.setRemoved();
+ }
+ if (mHeadsUpWrapper != null) {
+ mHeadsUpWrapper.setRemoved();
+ }
}
public void setContentHeightAnimating(boolean animating) {
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 20e8b73..1116106 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
@@ -39,6 +39,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.internal.widget.MediaNotificationView;
import com.android.systemui.Dependency;
import com.android.systemui.statusbar.NotificationMediaManager;
import com.android.systemui.statusbar.TransformableView;
@@ -67,6 +68,7 @@
private View mSeekBarView;
private Context mContext;
private MetricsLogger mMetricsLogger;
+ private boolean mIsViewVisible;
@VisibleForTesting
protected SeekBar.OnSeekBarChangeListener mSeekListener =
@@ -88,11 +90,46 @@
}
};
+ private MediaNotificationView.VisibilityChangeListener mVisibilityListener =
+ new MediaNotificationView.VisibilityChangeListener() {
+ @Override
+ public void onAggregatedVisibilityChanged(boolean isVisible) {
+ mIsViewVisible = isVisible;
+ if (isVisible && mMediaController != null) {
+ // Restart timer if we're currently playing and didn't already have one going
+ PlaybackState state = mMediaController.getPlaybackState();
+ if (state != null && state.getState() == PlaybackState.STATE_PLAYING
+ && mSeekBarTimer == null && mSeekBarView != null
+ && mSeekBarView.getVisibility() != View.GONE) {
+ startTimer();
+ }
+ } else {
+ clearTimer();
+ }
+ }
+ };
+
+ private View.OnAttachStateChangeListener mAttachStateListener =
+ new View.OnAttachStateChangeListener() {
+ @Override
+ public void onViewAttachedToWindow(View v) {
+ }
+
+ @Override
+ public void onViewDetachedFromWindow(View v) {
+ mIsViewVisible = false;
+ }
+ };
+
private MediaController.Callback mMediaCallback = new MediaController.Callback() {
@Override
public void onSessionDestroyed() {
clearTimer();
mMediaController.unregisterCallback(this);
+ if (mView instanceof MediaNotificationView) {
+ ((MediaNotificationView) mView).removeVisibilityListener(mVisibilityListener);
+ mView.removeOnAttachStateChangeListener(mAttachStateListener);
+ }
}
@Override
@@ -126,10 +163,17 @@
mContext = ctx;
mMediaManager = Dependency.get(NotificationMediaManager.class);
mMetricsLogger = Dependency.get(MetricsLogger.class);
+
+ if (mView instanceof MediaNotificationView) {
+ MediaNotificationView mediaView = (MediaNotificationView) mView;
+ mediaView.addVisibilityListener(mVisibilityListener);
+ mView.addOnAttachStateChangeListener(mAttachStateListener);
+ }
}
private void resolveViews() {
mActions = mView.findViewById(com.android.internal.R.id.media_actions);
+ mIsViewVisible = mView.isShown();
final MediaSession.Token token = mRow.getEntry().notification.getNotification().extras
.getParcelable(Notification.EXTRA_MEDIA_SESSION);
@@ -208,24 +252,37 @@
private void startTimer() {
clearTimer();
- mSeekBarTimer = new Timer(true /* isDaemon */);
- mSeekBarTimer.schedule(new TimerTask() {
- @Override
- public void run() {
- mHandler.post(mOnUpdateTimerTick);
- }
- }, 0, PROGRESS_UPDATE_INTERVAL);
+ if (mIsViewVisible) {
+ mSeekBarTimer = new Timer(true /* isDaemon */);
+ mSeekBarTimer.schedule(new TimerTask() {
+ @Override
+ public void run() {
+ mHandler.post(mOnUpdateTimerTick);
+ }
+ }, 0, PROGRESS_UPDATE_INTERVAL);
+ }
}
private void clearTimer() {
if (mSeekBarTimer != null) {
- // TODO: also trigger this when the notification panel is collapsed
mSeekBarTimer.cancel();
mSeekBarTimer.purge();
mSeekBarTimer = null;
}
}
+ @Override
+ public void setRemoved() {
+ clearTimer();
+ if (mMediaController != null) {
+ mMediaController.unregisterCallback(mMediaCallback);
+ }
+ if (mView instanceof MediaNotificationView) {
+ ((MediaNotificationView) mView).removeVisibilityListener(mVisibilityListener);
+ mView.removeOnAttachStateChangeListener(mAttachStateListener);
+ }
+ }
+
private boolean canSeekMedia(@Nullable PlaybackState state) {
if (state == null) {
return false;
@@ -261,7 +318,6 @@
public void run() {
if (mMediaController != null && mSeekBar != null) {
PlaybackState playbackState = mMediaController.getPlaybackState();
-
if (playbackState != null) {
updatePlaybackUi(playbackState);
} else {
@@ -274,6 +330,10 @@
};
private void updatePlaybackUi(PlaybackState state) {
+ if (mSeekBar == null || mSeekBarElapsedTime == null) {
+ return;
+ }
+
long position = state.getPosition();
mSeekBar.setProgress((int) position);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java
index 47906a7..3950003 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java
@@ -261,6 +261,12 @@
mView.setVisibility(visible ? View.VISIBLE : View.INVISIBLE);
}
+ /**
+ * Called to indicate this view is removed
+ */
+ public void setRemoved() {
+ }
+
public int getCustomBackgroundColor() {
// Parent notifications should always use the normal background color
return mRow.isSummaryWithChildren() ? 0 : mBackgroundColor;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
index 10b48e7..bb6a38e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
@@ -207,10 +207,6 @@
return SystemProperties.get(propName, mContext.getString(resId));
}
- public boolean getPickupPerformsProxCheck() {
- return mContext.getResources().getBoolean(R.bool.doze_pickup_performs_proximity_check);
- }
-
public int getPulseVisibleDurationExtended() {
return 2 * getPulseVisibleDuration();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java
index e0c6c55..daf4ab8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java
@@ -31,6 +31,7 @@
import android.os.Looper;
import android.os.RemoteException;
import android.os.SystemClock;
+import android.os.SystemProperties;
import android.util.Log;
import android.util.MathUtils;
import android.view.Gravity;
@@ -66,7 +67,8 @@
public class EdgeBackGestureHandler implements DisplayListener {
private static final String TAG = "EdgeBackGestureHandler";
- private static final int MAX_LONG_PRESS_TIMEOUT = 250;
+ private static final int MAX_LONG_PRESS_TIMEOUT = SystemProperties.getInt(
+ "gestures.back_timeout", 250);
private final IPinnedStackListener.Stub mImeChangedListener = new IPinnedStackListener.Stub() {
@Override
@@ -295,6 +297,7 @@
return mSamplingRect;
}
});
+ mRegionSamplingHelper.setWindowVisible(true);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java
index d2023ec..dcb349b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java
@@ -79,10 +79,13 @@
IWallpaperManager service = IWallpaperManager.Stub.asInterface(
ServiceManager.getService(Context.WALLPAPER_SERVICE));
- try {
- service.setLockWallpaperCallback(this);
- } catch (RemoteException e) {
- Log.e(TAG, "System dead?" + e);
+ if (service != null) {
+ // Service is disabled on some devices like Automotive
+ try {
+ service.setLockWallpaperCallback(this);
+ } catch (RemoteException e) {
+ Log.e(TAG, "System dead?" + e);
+ }
}
}
@@ -108,6 +111,11 @@
public LoaderResult loadBitmap(int currentUserId, UserHandle selectedUser) {
// May be called on any thread - only use thread safe operations.
+ if (!mWallpaperManager.isWallpaperSupported()) {
+ // When wallpaper is not supported, show the system wallpaper
+ return LoaderResult.success(null);
+ }
+
// Prefer the selected user (when specified) over the current user for the FLAG_SET_LOCK
// wallpaper.
final int lockWallpaperUserId =
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavBarTintController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavBarTintController.java
deleted file mode 100644
index 8bb8ca2..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavBarTintController.java
+++ /dev/null
@@ -1,210 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.statusbar.phone;
-
-import static android.view.Display.DEFAULT_DISPLAY;
-import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.graphics.Point;
-import android.graphics.Rect;
-import android.os.Handler;
-import android.view.CompositionSamplingListener;
-import android.view.View;
-
-import com.android.systemui.R;
-import com.android.systemui.shared.system.QuickStepContract;
-
-import java.io.PrintWriter;
-
-/**
- * Updates the nav bar tint based on the color of the content behind the nav bar.
- */
-public class NavBarTintController implements View.OnAttachStateChangeListener,
- View.OnLayoutChangeListener {
-
- public static final int MIN_COLOR_ADAPT_TRANSITION_TIME = 400;
- public static final int DEFAULT_COLOR_ADAPT_TRANSITION_TIME = 1700;
-
- private final Handler mHandler = new Handler();
- private final NavigationBarView mNavigationBarView;
- private final LightBarTransitionsController mLightBarController;
- private int mNavBarMode = NAV_BAR_MODE_3BUTTON;
- private boolean mWindowVisible;
-
- private final CompositionSamplingListener mSamplingListener;
- private final Runnable mUpdateSamplingListener = this::updateSamplingListener;
- private final Rect mSamplingBounds = new Rect();
- private boolean mSamplingEnabled = false;
- private boolean mSamplingListenerRegistered = false;
-
- private float mLastMedianLuma;
- private float mCurrentMedianLuma;
- private boolean mUpdateOnNextDraw;
-
- private final int mNavBarHeight;
- private final int mNavColorSampleMargin;
-
- // Passing the threshold of this luminance value will make the button black otherwise white
- private final float mLuminanceThreshold;
- private final float mLuminanceChangeThreshold;
-
- public NavBarTintController(NavigationBarView navigationBarView,
- LightBarTransitionsController lightBarController) {
- mSamplingListener = new CompositionSamplingListener(
- navigationBarView.getContext().getMainExecutor()) {
- @Override
- public void onSampleCollected(float medianLuma) {
- updateTint(medianLuma);
- }
- };
- mNavigationBarView = navigationBarView;
- mNavigationBarView.addOnAttachStateChangeListener(this);
- mNavigationBarView.addOnLayoutChangeListener(this);
- mLightBarController = lightBarController;
-
- final Resources res = navigationBarView.getResources();
- mNavBarHeight = res.getDimensionPixelSize(R.dimen.navigation_bar_height);
- mNavColorSampleMargin =
- res.getDimensionPixelSize(R.dimen.navigation_handle_sample_horizontal_margin);
- mLuminanceThreshold = res.getFloat(R.dimen.navigation_luminance_threshold);
- mLuminanceChangeThreshold = res.getFloat(R.dimen.navigation_luminance_change_threshold);
- }
-
- void onDraw() {
- if (mUpdateOnNextDraw) {
- mUpdateOnNextDraw = false;
- requestUpdateSamplingListener();
- }
- }
-
- void start() {
- if (!isEnabled(mNavigationBarView.getContext(), mNavBarMode)) {
- return;
- }
- mSamplingEnabled = true;
- // Defer calling updateSamplingListener since we may have just reinflated prior to this
- requestUpdateSamplingListener();
- }
-
- void stop() {
- mSamplingEnabled = false;
- requestUpdateSamplingListener();
- }
-
- @Override
- public void onViewAttachedToWindow(View view) {
- requestUpdateSamplingListener();
- }
-
- @Override
- public void onViewDetachedFromWindow(View view) {
- // Defer calling updateSamplingListener the attach info has not yet been reset
- requestUpdateSamplingListener();
- }
-
- @Override
- public void onLayoutChange(View v, int left, int top, int right, int bottom,
- int oldLeft, int oldTop, int oldRight, int oldBottom) {
- mSamplingBounds.setEmpty();
- // TODO: Extend this to 2/3 button layout as well
- View view = mNavigationBarView.getHomeHandle().getCurrentView();
- if (view != null) {
- int[] pos = new int[2];
- view.getLocationOnScreen(pos);
- Point displaySize = new Point();
- view.getContext().getDisplay().getRealSize(displaySize);
- final Rect samplingBounds = new Rect(pos[0] - mNavColorSampleMargin,
- displaySize.y - mNavBarHeight, pos[0] + view.getWidth() + mNavColorSampleMargin,
- displaySize.y);
- if (!samplingBounds.equals(mSamplingBounds)) {
- mSamplingBounds.set(samplingBounds);
- requestUpdateSamplingListener();
- }
- }
- }
-
- private void requestUpdateSamplingListener() {
- mHandler.removeCallbacks(mUpdateSamplingListener);
- mHandler.post(mUpdateSamplingListener);
- }
-
- private void updateSamplingListener() {
- if (mSamplingListenerRegistered) {
- mSamplingListenerRegistered = false;
- CompositionSamplingListener.unregister(mSamplingListener);
- }
- if (mSamplingEnabled && mWindowVisible && !mSamplingBounds.isEmpty()
- && mNavigationBarView.isAttachedToWindow()) {
- if (!mNavigationBarView.getViewRootImpl().getSurfaceControl().isValid()) {
- // The view may still be attached, but the surface backing the window can be
- // destroyed, so wait until the next draw to update the listener again
- mUpdateOnNextDraw = true;
- return;
- }
- mSamplingListenerRegistered = true;
- CompositionSamplingListener.register(mSamplingListener, DEFAULT_DISPLAY,
- mNavigationBarView.getViewRootImpl().getSurfaceControl(),
- mSamplingBounds);
- }
- }
-
- private void updateTint(float medianLuma) {
- mLastMedianLuma = medianLuma;
-
- // If the difference between the new luma and the current luma is larger than threshold
- // then apply the current luma, this is to prevent small changes causing colors to flicker
- if (Math.abs(mCurrentMedianLuma - mLastMedianLuma) > mLuminanceChangeThreshold) {
- if (medianLuma > mLuminanceThreshold) {
- // Black
- mLightBarController.setIconsDark(true /* dark */, true /* animate */);
- } else {
- // White
- mLightBarController.setIconsDark(false /* dark */, true /* animate */);
- }
- mCurrentMedianLuma = medianLuma;
- }
- }
-
- public void setWindowVisible(boolean visible) {
- mWindowVisible = visible;
- requestUpdateSamplingListener();
- }
-
- public void onNavigationModeChanged(int mode) {
- mNavBarMode = mode;
- }
-
- void dump(PrintWriter pw) {
- pw.println("NavBarTintController:");
- pw.println(" navBar isAttached: " + mNavigationBarView.isAttachedToWindow());
- pw.println(" navBar isScValid: " + (mNavigationBarView.isAttachedToWindow()
- ? mNavigationBarView.getViewRootImpl().getSurfaceControl().isValid()
- : "false"));
- pw.println(" mSamplingListenerRegistered: " + mSamplingListenerRegistered);
- pw.println(" mSamplingBounds: " + mSamplingBounds);
- pw.println(" mLastMedianLuma: " + mLastMedianLuma);
- pw.println(" mCurrentMedianLuma: " + mCurrentMedianLuma);
- pw.println(" mWindowVisible: " + mWindowVisible);
- }
-
- public static boolean isEnabled(Context context, int navBarMode) {
- return context.getDisplayId() == DEFAULT_DISPLAY
- && QuickStepContract.isGesturalMode(navBarMode);
- }
-}
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 e9731c5..5d3f3ac 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
@@ -1063,16 +1063,7 @@
if (Intent.ACTION_SCREEN_OFF.equals(action)
|| Intent.ACTION_SCREEN_ON.equals(action)) {
notifyNavigationBarScreenOn();
-
- if (Intent.ACTION_SCREEN_ON.equals(action)) {
- // Enabled and screen is on, start it again if enabled
- if (NavBarTintController.isEnabled(getContext(), mNavBarMode)) {
- mNavigationBarView.getTintController().start();
- }
- } else {
- // Screen off disable it
- mNavigationBarView.getTintController().stop();
- }
+ mNavigationBarView.onScreenStateChanged(Intent.ACTION_SCREEN_ON.equals(action));
}
if (Intent.ACTION_USER_SWITCHED.equals(action)) {
// The accessibility settings may be different for the new user
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 23cc0fc..3b59031 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java
@@ -18,8 +18,7 @@
import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON;
-import static com.android.systemui.statusbar.phone.NavBarTintController.DEFAULT_COLOR_ADAPT_TRANSITION_TIME;
-import static com.android.systemui.statusbar.phone.NavBarTintController.MIN_COLOR_ADAPT_TRANSITION_TIME;
+import static com.android.systemui.util.Utils.isGesturalModeOnDefaultDisplay;
import android.content.Context;
import android.graphics.Rect;
@@ -42,6 +41,9 @@
public final class NavigationBarTransitions extends BarTransitions implements
LightBarTransitionsController.DarkIntensityApplier {
+ public static final int MIN_COLOR_ADAPT_TRANSITION_TIME = 400;
+ public static final int DEFAULT_COLOR_ADAPT_TRANSITION_TIME = 1700;
+
/**
* Notified when the color of nav bar elements changes.
*/
@@ -124,7 +126,7 @@
@Override
public void setAutoDim(boolean autoDim) {
// Ensure we aren't in gestural nav if we are triggering auto dim
- if (autoDim && NavBarTintController.isEnabled(mView.getContext(), mNavBarMode)) return;
+ if (autoDim && isGesturalModeOnDefaultDisplay(mView.getContext(), mNavBarMode)) return;
if (mAutoDim == autoDim) return;
mAutoDim = autoDim;
applyLightsOut(true, false);
@@ -201,7 +203,7 @@
@Override
public int getTintAnimationDuration() {
- if (NavBarTintController.isEnabled(mView.getContext(), mNavBarMode)) {
+ if (isGesturalModeOnDefaultDisplay(mView.getContext(), mNavBarMode)) {
return Math.max(DEFAULT_COLOR_ADAPT_TRANSITION_TIME, MIN_COLOR_ADAPT_TRANSITION_TIME);
}
return LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION;
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 6bfa048..fdee278 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -16,8 +16,6 @@
package com.android.systemui.statusbar.phone;
-import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON;
-
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_HOME_DISABLED;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_OVERVIEW_DISABLED;
@@ -26,6 +24,7 @@
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_SEARCH_DISABLED;
import static com.android.systemui.shared.system.QuickStepContract.isGesturalMode;
import static com.android.systemui.statusbar.phone.BarTransitions.MODE_OPAQUE;
+import static com.android.systemui.util.Utils.isGesturalModeOnDefaultDisplay;
import android.animation.LayoutTransition;
import android.animation.LayoutTransition.TransitionListener;
@@ -89,6 +88,8 @@
final static boolean SLIPPERY_WHEN_DISABLED = true;
final static boolean ALTERNATE_CAR_MODE_UI = false;
+ private final RegionSamplingHelper mRegionSamplingHelper;
+ private final int mNavColorSampleMargin;
View mCurrentView = null;
private View mVertical;
@@ -101,7 +102,7 @@
boolean mLongClickableAccessibilityButton;
int mDisabledFlags = 0;
int mNavigationIconHints = 0;
- private int mNavBarMode = NAV_BAR_MODE_3BUTTON;
+ private int mNavBarMode;
private Rect mHomeButtonBounds = new Rect();
private Rect mBackButtonBounds = new Rect();
@@ -143,14 +144,13 @@
private FloatingRotationButton mFloatingRotationButton;
private RotationButtonController mRotationButtonController;
- private NavBarTintController mTintController;
-
/**
* Helper that is responsible for showing the right toast when a disallowed activity operation
* occurred. In pinned mode, we show instructions on how to break out of this mode, whilst in
* fully locked mode we only show that unlocking is blocked.
*/
private ScreenPinningNotify mScreenPinningNotify;
+ private Rect mSamplingBounds = new Rect();
private class NavTransitionListener implements TransitionListener {
private boolean mBackTransitioning;
@@ -305,12 +305,30 @@
mButtonDispatchers.put(R.id.menu_container, mContextualButtonGroup);
mDeadZone = new DeadZone(this);
- mEdgeBackGestureHandler = new EdgeBackGestureHandler(context, mOverviewProxyService);
- mTintController = new NavBarTintController(this, getLightTransitionsController());
- }
+ mNavColorSampleMargin =
+ getResources()
+ .getDimensionPixelSize(R.dimen.navigation_handle_sample_horizontal_margin);
- public NavBarTintController getTintController() {
- return mTintController;
+ mEdgeBackGestureHandler = new EdgeBackGestureHandler(context, mOverviewProxyService);
+ mRegionSamplingHelper = new RegionSamplingHelper(this,
+ new RegionSamplingHelper.SamplingCallback() {
+ @Override
+ public void onRegionDarknessChanged(boolean isRegionDark) {
+ getLightTransitionsController().setIconsDark(!isRegionDark ,
+ true /* animate */);
+ }
+
+ @Override
+ public Rect getSampledRegion(View sampledView) {
+ updateSamplingRect();
+ return mSamplingBounds;
+ }
+
+ @Override
+ public boolean isSamplingEnabled() {
+ return isGesturalModeOnDefaultDisplay(getContext(), mNavBarMode);
+ }
+ });
}
public NavigationBarTransitions getBarTransitions() {
@@ -326,12 +344,6 @@
updatePanelSystemUiStateFlags();
}
- @Override
- protected void dispatchDraw(Canvas canvas) {
- super.dispatchDraw(canvas);
- mTintController.onDraw();
- }
-
public void setOnVerticalChangedListener(OnVerticalChangedListener onVerticalChangedListener) {
mOnVerticalChangedListener = onVerticalChangedListener;
notifyVerticalChangedListener(mIsVertical);
@@ -352,10 +364,10 @@
if (newMode == MODE_OPAQUE) {
// If the nav bar background is opaque, stop auto tinting since we know the icons are
// showing over a dark background
- mTintController.stop();
+ mRegionSamplingHelper.stop();
getLightTransitionsController().setIconsDark(false /* dark */, true /* animate */);
} else {
- mTintController.start();
+ mRegionSamplingHelper.start(mSamplingBounds);
}
}
@@ -535,8 +547,19 @@
return KeyButtonDrawable.create(mContext, icon, hasShadow);
}
+ /** To be called when screen lock/unlock state changes */
+ public void onScreenStateChanged(boolean isScreenOn) {
+ if (isScreenOn) {
+ if (isGesturalModeOnDefaultDisplay(getContext(), mNavBarMode)) {
+ mRegionSamplingHelper.start(mSamplingBounds);
+ }
+ } else {
+ mRegionSamplingHelper.stop();
+ }
+ }
+
public void setWindowVisible(boolean visible) {
- mTintController.setWindowVisible(visible);
+ mRegionSamplingHelper.setWindowVisible(visible);
mRotationButtonController.onNavigationBarWindowVisibilityChange(visible);
}
@@ -619,6 +642,10 @@
// Always disable recents when alternate car mode UI is active and for secondary displays.
boolean disableRecent = isRecentsButtonDisabled();
+ // Disable the home handle if both hone and recents are disabled
+ boolean disableHomeHandle = disableRecent
+ && ((mDisabledFlags & View.STATUS_BAR_DISABLE_HOME) != 0);
+
boolean disableBack = !useAltBack && (isGesturalMode(mNavBarMode)
|| ((mDisabledFlags & View.STATUS_BAR_DISABLE_BACK) != 0));
@@ -649,6 +676,7 @@
getBackButton().setVisibility(disableBack ? View.INVISIBLE : View.VISIBLE);
getHomeButton().setVisibility(disableHome ? View.INVISIBLE : View.VISIBLE);
getRecentsButton().setVisibility(disableRecent ? View.INVISIBLE : View.VISIBLE);
+ getHomeHandle().setVisibility(disableHomeHandle ? View.INVISIBLE : View.VISIBLE);
}
@VisibleForTesting
@@ -794,13 +822,7 @@
mRecentsOnboarding.onNavigationModeChanged(mNavBarMode);
getRotateSuggestionButton().onNavigationModeChanged(mNavBarMode);
- // Color adaption is tied with showing home handle, only avaliable if visible
- mTintController.onNavigationModeChanged(mNavBarMode);
- if (isGesturalMode(mNavBarMode)) {
- mTintController.start();
- } else {
- mTintController.stop();
- }
+ mRegionSamplingHelper.start(mSamplingBounds);
}
public void setAccessibilityButtonState(final boolean visible, final boolean longClickable) {
@@ -831,6 +853,24 @@
super.onDraw(canvas);
}
+ private void updateSamplingRect() {
+ mSamplingBounds.setEmpty();
+ // TODO: Extend this to 2/3 button layout as well
+ View view = getHomeHandle().getCurrentView();
+
+ if (view != null) {
+ int[] pos = new int[2];
+ view.getLocationOnScreen(pos);
+ Point displaySize = new Point();
+ view.getContext().getDisplay().getRealSize(displaySize);
+ final Rect samplingBounds = new Rect(pos[0] - mNavColorSampleMargin,
+ displaySize.y - getNavBarHeight(),
+ pos[0] + view.getWidth() + mNavColorSampleMargin,
+ displaySize.y);
+ mSamplingBounds.set(samplingBounds);
+ }
+ }
+
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
@@ -979,6 +1019,14 @@
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
+ private int getNavBarHeight() {
+ return mIsVertical
+ ? getResources().getDimensionPixelSize(
+ com.android.internal.R.dimen.navigation_bar_height_landscape)
+ : getResources().getDimensionPixelSize(
+ com.android.internal.R.dimen.navigation_bar_height);
+ }
+
private void notifyVerticalChangedListener(boolean newVertical) {
if (mOnVerticalChangedListener != null) {
mOnVerticalChangedListener.onVerticalChanged(newVertical);
@@ -1125,7 +1173,7 @@
mContextualButtonGroup.dump(pw);
mRecentsOnboarding.dump(pw);
- mTintController.dump(pw);
+ mRegionSamplingHelper.dump(pw);
mEdgeBackGestureHandler.dump(pw);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationPrototypeController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationPrototypeController.java
index 9988c85..5d8044f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationPrototypeController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationPrototypeController.java
@@ -16,7 +16,7 @@
package com.android.systemui.statusbar.phone;
-import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL;
+import static android.view.Display.DEFAULT_DISPLAY;
import android.annotation.IntDef;
import android.content.ComponentCallbacks;
@@ -29,8 +29,6 @@
import android.os.Handler;
import android.provider.Settings;
-import com.android.systemui.shared.system.QuickStepContract;
-
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -120,8 +118,7 @@
} else if (path.endsWith(HIDE_HOME_BUTTON_SETTING)) {
mListener.onHomeButtonVisibilityChanged(!hideHomeButton());
} else if (path.endsWith(NAV_COLOR_ADAPT_ENABLE_SETTING)) {
- mListener.onColorAdaptChanged(
- NavBarTintController.isEnabled(mContext, NAV_BAR_MODE_GESTURAL));
+ mListener.onColorAdaptChanged(mContext.getDisplayId() == DEFAULT_DISPLAY);
} else if (path.endsWith(SHOW_HOME_HANDLE_SETTING)) {
mListener.onHomeHandleVisiblilityChanged(showHomeHandle());
} else if (path.endsWith(ENABLE_ASSISTANT_GESTURE)) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/RegionSamplingHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/RegionSamplingHelper.java
index 8026f65..c1ff572 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/RegionSamplingHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/RegionSamplingHelper.java
@@ -29,6 +29,8 @@
import com.android.systemui.R;
+import java.io.PrintWriter;
+
/**
* A helper class to sample regions on the screen and inspect its luminosity.
*/
@@ -62,6 +64,7 @@
private final float mLuminanceThreshold;
private final float mLuminanceChangeThreshold;
private boolean mFirstSamplingAfterStart;
+ private boolean mWindowVisible;
private SurfaceControl mRegisteredStopLayer = null;
private ViewTreeObserver.OnDrawListener mUpdateOnDraw = new ViewTreeObserver.OnDrawListener() {
@Override
@@ -148,7 +151,9 @@
}
private void updateSamplingListener() {
- boolean isSamplingEnabled = mSamplingEnabled && !mSamplingRequestBounds.isEmpty()
+ boolean isSamplingEnabled = mSamplingEnabled
+ && !mSamplingRequestBounds.isEmpty()
+ && mWindowVisible
&& (mSampledView.isAttachedToWindow() || mFirstSamplingAfterStart);
if (isSamplingEnabled) {
ViewRootImpl viewRootImpl = mSampledView.getViewRootImpl();
@@ -216,6 +221,24 @@
}
}
+ void setWindowVisible(boolean visible) {
+ mWindowVisible = visible;
+ updateSamplingListener();
+ }
+
+ void dump(PrintWriter pw) {
+ pw.println("RegionSamplingHelper:");
+ pw.println(" sampleView isAttached: " + mSampledView.isAttachedToWindow());
+ pw.println(" sampleView isScValid: " + (mSampledView.isAttachedToWindow()
+ ? mSampledView.getViewRootImpl().getSurfaceControl().isValid()
+ : "false"));
+ pw.println(" mSamplingListenerRegistered: " + mSamplingListenerRegistered);
+ pw.println(" mSamplingRequestBounds: " + mSamplingRequestBounds);
+ pw.println(" mLastMedianLuma: " + mLastMedianLuma);
+ pw.println(" mCurrentMedianLuma: " + mCurrentMedianLuma);
+ pw.println(" mWindowVisible: " + mWindowVisible);
+ }
+
public interface SamplingCallback {
/**
* Called when the darkness of the sampled region changes
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 b12bf5c..a7262cf 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -47,6 +47,7 @@
import com.android.systemui.colorextraction.SysuiColorExtractor;
import com.android.systemui.statusbar.ScrimView;
import com.android.systemui.statusbar.notification.stack.ViewState;
+import com.android.systemui.statusbar.policy.KeyguardMonitor;
import com.android.systemui.util.AlarmTimeout;
import com.android.systemui.util.wakelock.DelayedWakeLock;
import com.android.systemui.util.wakelock.WakeLock;
@@ -177,7 +178,7 @@
public ScrimController(ScrimView scrimBehind, ScrimView scrimInFront,
TriConsumer<ScrimState, Float, GradientColors> scrimStateListener,
Consumer<Integer> scrimVisibleListener, DozeParameters dozeParameters,
- AlarmManager alarmManager) {
+ AlarmManager alarmManager, KeyguardMonitor keyguardMonitor) {
mScrimBehind = scrimBehind;
mScrimInFront = scrimInFront;
mScrimStateListener = scrimStateListener;
@@ -197,6 +198,13 @@
// to make sure that text on top of it is legible.
mScrimBehindAlpha = mScrimBehindAlphaResValue;
mDozeParameters = dozeParameters;
+ keyguardMonitor.addCallback(new KeyguardMonitor.Callback() {
+ @Override
+ public void onKeyguardFadingAwayChanged() {
+ setKeyguardFadingAway(keyguardMonitor.isKeyguardFadingAway(),
+ keyguardMonitor.getKeyguardFadingAwayDuration());
+ }
+ });
mColorExtractor = Dependency.get(SysuiColorExtractor.class);
mColorExtractor.addOnColorsChangedListener(this);
@@ -948,9 +956,9 @@
}
}
- public void setUnlockIsFading(boolean unlockFading) {
+ private void setKeyguardFadingAway(boolean fadingAway, long duration) {
for (ScrimState state : ScrimState.values()) {
- state.setUnlockIsFading(unlockFading);
+ state.setKeyguardFadingAway(fadingAway, duration);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java
index c706062..9fdd3b8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java
@@ -133,6 +133,12 @@
mBlankScreen = mDisplayRequiresBlanking;
mAnimationDuration = mWakeLockScreenSensorActive
? ScrimController.ANIMATION_DURATION_LONG : ScrimController.ANIMATION_DURATION;
+
+ // Wake sensor will show the wallpaper, let's fade from black. Otherwise it will
+ // feel like the screen is flashing if the wallpaper is light.
+ if (mWakeLockScreenSensorActive && previousState == AOD) {
+ updateScrimColor(mScrimBehind, 1f /* alpha */, Color.BLACK);
+ }
}
@Override
@@ -150,8 +156,8 @@
public void prepare(ScrimState previousState) {
mCurrentBehindAlpha = 0;
mCurrentInFrontAlpha = 0;
- mAnimationDuration = mUnlockIsFading
- ? KeyguardBypassController.BYPASS_PANEL_FADE_DURATION
+ mAnimationDuration = mKeyguardFadingAway
+ ? mKeyguardFadingAwayDuration
: StatusBar.FADE_KEYGUARD_DURATION;
mAnimateChange = !mLaunchingAffordanceWithPreview;
@@ -203,7 +209,8 @@
boolean mHasBackdrop;
boolean mLaunchingAffordanceWithPreview;
boolean mWakeLockScreenSensorActive;
- boolean mUnlockIsFading;
+ boolean mKeyguardFadingAway;
+ long mKeyguardFadingAwayDuration;
ScrimState(int index) {
mIndex = index;
@@ -292,7 +299,8 @@
mWakeLockScreenSensorActive = active;
}
- public void setUnlockIsFading(boolean unlockIsFading) {
- mUnlockIsFading = unlockIsFading;
+ public void setKeyguardFadingAway(boolean fadingAway, long duration) {
+ mKeyguardFadingAway = fadingAway;
+ mKeyguardFadingAwayDuration = duration;
}
}
\ No newline at end of file
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 4f9df43..f158ca1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -480,15 +480,17 @@
private NotificationMediaManager mMediaManager;
protected NotificationLockscreenUserManager mLockscreenUserManager;
protected NotificationRemoteInputManager mRemoteInputManager;
+ private boolean mWallpaperSupported;
private final BroadcastReceiver mWallpaperChangedReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
- WallpaperManager wallpaperManager = context.getSystemService(WallpaperManager.class);
- if (wallpaperManager == null) {
- Log.w(TAG, "WallpaperManager not available");
+ if (!mWallpaperSupported) {
+ // Receiver should not have been registered at all...
+ Log.wtf(TAG, "WallpaperManager not supported");
return;
}
+ WallpaperManager wallpaperManager = context.getSystemService(WallpaperManager.class);
WallpaperInfo info = wallpaperManager.getWallpaperInfo(UserHandle.USER_CURRENT);
final boolean deviceSupportsAodWallpaper = mContext.getResources().getBoolean(
com.android.internal.R.bool.config_dozeSupportsAodWallpaper);
@@ -715,11 +717,18 @@
createAndAddWindows(result);
- // 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 */);
- mWallpaperChangedReceiver.onReceive(mContext, null);
+ mWallpaperSupported =
+ mContext.getSystemService(WallpaperManager.class).isWallpaperSupported();
+
+ 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 */);
+ mWallpaperChangedReceiver.onReceive(mContext, null);
+ } else if (DEBUG) {
+ Log.v(TAG, "start(): no wallpaper service ");
+ }
// Set up the initial notification state. This needs to happen before CommandQueue.disable()
setUpPresenter();
@@ -754,12 +763,14 @@
mContext.registerReceiver(mBannerActionBroadcastReceiver, internalFilter, PERMISSION_SELF,
null);
- IWallpaperManager wallpaperManager = IWallpaperManager.Stub.asInterface(
- ServiceManager.getService(Context.WALLPAPER_SERVICE));
- try {
- wallpaperManager.setInAmbientMode(false /* ambientMode */, 0L /* duration */);
- } catch (RemoteException e) {
- // Just pass, nothing critical.
+ if (mWallpaperSupported) {
+ IWallpaperManager wallpaperManager = IWallpaperManager.Stub.asInterface(
+ ServiceManager.getService(Context.WALLPAPER_SERVICE));
+ try {
+ wallpaperManager.setInAmbientMode(false /* ambientMode */, 0L /* duration */);
+ } catch (RemoteException e) {
+ // Just pass, nothing critical.
+ }
}
// end old BaseStatusBar.start().
@@ -937,7 +948,8 @@
mStatusBarWindow.onScrimVisibilityChanged(scrimsVisible);
}
}, DozeParameters.getInstance(mContext),
- mContext.getSystemService(AlarmManager.class));
+ mContext.getSystemService(AlarmManager.class),
+ mKeyguardMonitor);
mNotificationPanel.initDependencies(this, mGroupManager, mNotificationShelf,
mHeadsUpManager, mNotificationIconAreaController, mScrimController);
mDozeScrimController = new DozeScrimController(DozeParameters.getInstance(context));
@@ -2311,6 +2323,7 @@
pw.println(Settings.Global.zenModeToString(Settings.Global.getInt(
mContext.getContentResolver(), Settings.Global.ZEN_MODE,
Settings.Global.ZEN_MODE_OFF)));
+ pw.print(" mWallpaperSupported= "); pw.println(mWallpaperSupported);
if (mStatusBarView != null) {
dumpBarTransitions(pw, "mStatusBarView", mStatusBarView.getBarTransitions());
@@ -2691,7 +2704,9 @@
public void setLockscreenUser(int newUserId) {
mLockscreenWallpaper.setCurrentUser(newUserId);
mScrimController.setCurrentUser(newUserId);
- mWallpaperChangedReceiver.onReceive(mContext, null);
+ if (mWallpaperSupported) {
+ mWallpaperChangedReceiver.onReceive(mContext, null);
+ }
}
/**
@@ -3860,7 +3875,6 @@
public void notifyBiometricAuthModeChanged() {
updateDozing();
- mScrimController.setUnlockIsFading(mBiometricUnlockController.isUnlockFading());
updateScrimController();
mStatusBarWindow.onBiometricAuthModeChanged(mBiometricUnlockController.isWakeAndUnlock(),
mBiometricUnlockController.isBiometricUnlock());
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitor.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitor.java
index 070136e..e1ef809 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitor.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitor.java
@@ -76,7 +76,7 @@
}
interface Callback {
- void onKeyguardShowingChanged();
+ default void onKeyguardShowingChanged() {}
default void onKeyguardFadingAwayChanged() {}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitorImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitorImpl.java
index 8829be4..87ed14a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitorImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitorImpl.java
@@ -142,10 +142,10 @@
}
public void notifyKeyguardFadingAway(long delay, long fadeoutDuration, boolean isBypassFading) {
- setKeyguardFadingAway(true);
mKeyguardFadingAwayDelay = delay;
mKeyguardFadingAwayDuration = fadeoutDuration;
mBypassFadingAnimation = isBypassFading;
+ setKeyguardFadingAway(true);
}
private void setKeyguardFadingAway(boolean keyguardFadingAway) {
diff --git a/packages/SystemUI/src/com/android/systemui/util/Utils.java b/packages/SystemUI/src/com/android/systemui/util/Utils.java
index 1102bb7..92a8d84 100644
--- a/packages/SystemUI/src/com/android/systemui/util/Utils.java
+++ b/packages/SystemUI/src/com/android/systemui/util/Utils.java
@@ -14,12 +14,16 @@
package com.android.systemui.util;
+import static android.view.Display.DEFAULT_DISPLAY;
+
import android.Manifest;
+import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.view.View;
import com.android.systemui.SysUiServiceProvider;
+import com.android.systemui.shared.system.QuickStepContract;
import com.android.systemui.statusbar.CommandQueue;
import java.util.List;
@@ -110,4 +114,14 @@
return pm.queryIntentActivities(homeIntent, 0).isEmpty();
}
+ /**
+ * Returns {@code true} if the navMode is that of
+ * {@link android.view.WindowManagerPolicyConstants#NAV_BAR_MODE_GESTURAL} AND
+ * the context is that of the default display
+ */
+ public static boolean isGesturalModeOnDefaultDisplay(Context context, int navMode) {
+ return context.getDisplayId() == DEFAULT_DISPLAY
+ && QuickStepContract.isGesturalMode(navMode);
+ }
+
}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
index 7b133f2..24d6c4c 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
@@ -1020,12 +1020,11 @@
row.icon.setAlpha(iconEnabled ? 1 : 0.5f);
final int iconRes =
isRingVibrate ? R.drawable.ic_volume_ringer_vibrate
- : isRingSilent || zenMuted ? row.iconMuteRes
- : ss.routedToBluetooth ?
- (ss.muted ? R.drawable.ic_volume_media_bt_mute
- : R.drawable.ic_volume_media_bt)
- : mAutomute && ss.level == 0 ? row.iconMuteRes
- : (ss.muted ? row.iconMuteRes : row.iconRes);
+ : isRingSilent || zenMuted ? row.iconMuteRes
+ : ss.routedToBluetooth
+ ? isStreamMuted(ss) ? R.drawable.ic_volume_media_bt_mute
+ : R.drawable.ic_volume_media_bt
+ : isStreamMuted(ss) ? row.iconMuteRes : row.iconRes;
row.icon.setImageResource(iconRes);
row.iconState =
iconRes == R.drawable.ic_volume_ringer_vibrate ? Events.ICON_STATE_VIBRATE
@@ -1087,6 +1086,10 @@
updateVolumeRowSliderH(row, enableSlider, vlevel);
}
+ private boolean isStreamMuted(final StreamState streamState) {
+ return (mAutomute && streamState.level == 0) || streamState.muted;
+ }
+
private void updateVolumeRowTintH(VolumeRow row, boolean isActive) {
if (isActive) {
row.slider.requestFocus();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeConfigurationUtil.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeConfigurationUtil.java
index 2ed0970..0c124ff 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeConfigurationUtil.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeConfigurationUtil.java
@@ -37,7 +37,6 @@
when(params.getPulseOnSigMotion()).thenReturn(false);
when(params.getPickupVibrationThreshold()).thenReturn(0);
when(params.getProxCheckBeforePulse()).thenReturn(true);
- when(params.getPickupPerformsProxCheck()).thenReturn(true);
when(params.getPolicy()).thenReturn(mock(AlwaysOnDisplayPolicy.class));
when(params.doubleTapReportsTouchCoordinates()).thenReturn(false);
when(params.getDisplayNeedsBlanking()).thenReturn(false);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSensorsTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSensorsTest.java
index 7df45a3..cd6d1e0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSensorsTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSensorsTest.java
@@ -19,7 +19,6 @@
import static com.android.systemui.plugins.SensorManagerPlugin.Sensor.TYPE_WAKE_LOCK_SCREEN;
import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyFloat;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
@@ -79,8 +78,6 @@
private AlwaysOnDisplayPolicy mAlwaysOnDisplayPolicy;
@Mock
private TriggerSensor mTriggerSensor;
- @Mock
- private TriggerSensor mProxGatedTriggerSensor;
private SensorManagerPlugin.SensorEventListener mWakeLockScreenListener;
private TestableLooper mTestableLooper;
private DozeSensors mDozeSensors;
@@ -88,7 +85,6 @@
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
- when(mProxGatedTriggerSensor.performsProxCheck()).thenReturn(true);
mTestableLooper = TestableLooper.get(this);
when(mAmbientDisplayConfiguration.getWakeLockScreenDebounce()).thenReturn(5000L);
when(mAmbientDisplayConfiguration.alwaysOnEnabled(anyInt())).thenReturn(true);
@@ -106,14 +102,14 @@
mWakeLockScreenListener.onSensorChanged(mock(SensorManagerPlugin.SensorEvent.class));
mTestableLooper.processAllMessages();
verify(mCallback).onSensorPulse(eq(DozeLog.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN),
- anyBoolean(), anyFloat(), anyFloat(), eq(null));
+ anyFloat(), anyFloat(), eq(null));
mDozeSensors.requestTemporaryDisable();
reset(mCallback);
mWakeLockScreenListener.onSensorChanged(mock(SensorManagerPlugin.SensorEvent.class));
mTestableLooper.processAllMessages();
verify(mCallback, never()).onSensorPulse(eq(DozeLog.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN),
- anyBoolean(), anyFloat(), anyFloat(), eq(null));
+ anyFloat(), anyFloat(), eq(null));
}
@Test
@@ -132,20 +128,17 @@
}
@Test
- public void testSetPaused_onlyPausesNonGatedSensors() {
+ public void testSetPaused_doesntPause_sensors() {
mDozeSensors.setListening(true);
verify(mTriggerSensor).setListening(eq(true));
- verify(mProxGatedTriggerSensor).setListening(eq(true));
- clearInvocations(mTriggerSensor, mProxGatedTriggerSensor);
+ clearInvocations(mTriggerSensor);
mDozeSensors.setPaused(true);
- verify(mTriggerSensor).setListening(eq(false));
- verify(mProxGatedTriggerSensor).setListening(eq(true));
-
- clearInvocations(mTriggerSensor, mProxGatedTriggerSensor);
- mDozeSensors.setPaused(false);
verify(mTriggerSensor).setListening(eq(true));
- verify(mProxGatedTriggerSensor).setListening(eq(true));
+
+ clearInvocations(mTriggerSensor);
+ mDozeSensors.setListening(false);
+ verify(mTriggerSensor).setListening(eq(false));
}
private class TestableDozeSensors extends DozeSensors {
@@ -161,7 +154,7 @@
mWakeLockScreenListener = (PluginSensor) sensor;
}
}
- mSensors = new TriggerSensor[] {mTriggerSensor, mProxGatedTriggerSensor};
+ mSensors = new TriggerSensor[] {mTriggerSensor};
}
}
}
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 d464223..e190f99 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java
@@ -20,7 +20,6 @@
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.clearInvocations;
-import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
@@ -134,28 +133,4 @@
mTriggers.transitionTo(DozeMachine.State.DOZE, DozeMachine.State.FINISH);
verify(mDockManagerFake).removeListener(any());
}
-
- @Test
- public void testOnSensor_whenUndockedWithNearAndDoubleTapScreen_shouldNotWakeUp() {
- mSensors.getMockProximitySensor().sendProximityResult(false /* far */);
-
- mTriggers.onSensor(DozeLog.REASON_SENSOR_DOUBLE_TAP,
- false /* sensorPerformedProxCheck */, 50 /* screenX */, 50 /* screenY */,
- null /* rawValues */);
- verify(mMachine, never()).wakeUp();
- }
-
- @Test
- public void testOnSensor_whenDockedWithNearAndDoubleTapScreen_shouldWakeUp() {
- doReturn(true).when(mDockManagerFake).isDocked();
- doReturn(true).when(mParameters).getDisplayNeedsBlanking();
- mSensors.getMockProximitySensor().sendProximityResult(false /* far */);
-
- mTriggers.onSensor(DozeLog.REASON_SENSOR_DOUBLE_TAP,
- false /* sensorPerformedProxCheck */, 50 /* screenX */, 50 /* screenY */,
- null /* rawValues */);
-
- verify(mHost).setAodDimmingScrim(eq(1f));
- verify(mMachine).wakeUp();
- }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/recents/model/TaskKeyLruCacheTest.java b/packages/SystemUI/tests/src/com/android/systemui/shared/recents/model/TaskKeyLruCacheTest.java
index eb71dd6..de6c87c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shared/recents/model/TaskKeyLruCacheTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shared/recents/model/TaskKeyLruCacheTest.java
@@ -20,6 +20,10 @@
import static junit.framework.TestCase.assertEquals;
import static junit.framework.TestCase.assertNull;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
import android.test.suitebuilder.annotation.SmallTest;
import com.android.systemui.SysuiTestCase;
@@ -27,10 +31,10 @@
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
+import org.mockito.junit.MockitoJUnitRunner;
@SmallTest
-@RunWith(JUnit4.class)
+@RunWith(MockitoJUnitRunner.class)
public class TaskKeyLruCacheTest extends SysuiTestCase {
private static int sCacheSize = 3;
private static int sIdTask1 = 1;
@@ -38,13 +42,18 @@
private static int sIdTask3 = 3;
private static int sIdUser1 = 1;
- TaskKeyCache<Integer> mCache = new TaskKeyLruCache<>(sCacheSize, null);
- Task.TaskKey mKey1;
- Task.TaskKey mKey2;
- Task.TaskKey mKey3;
+ TaskKeyLruCache.EvictionCallback mEvictionCallback;
+
+ TaskKeyLruCache<Integer> mCache;
+ private Task.TaskKey mKey1;
+ private Task.TaskKey mKey2;
+ private Task.TaskKey mKey3;
@Before
public void setup() {
+ mEvictionCallback = mock(TaskKeyLruCache.EvictionCallback.class);
+ mCache = new TaskKeyLruCache<>(sCacheSize, mEvictionCallback);
+
mKey1 = new Task.TaskKey(sIdTask1, 0, null, null, sIdUser1, System.currentTimeMillis());
mKey2 = new Task.TaskKey(sIdTask2, 0, null, null, sIdUser1, System.currentTimeMillis());
mKey3 = new Task.TaskKey(sIdTask3, 0, null, null, sIdUser1, System.currentTimeMillis());
@@ -90,6 +99,7 @@
assertNull(mCache.get(mKey1));
assertEquals(3, mCache.mKeys.size());
assertEquals(mKey2, mCache.mKeys.valueAt(0));
+ verify(mEvictionCallback, times(1)).onEntryEvicted(mKey1);
}
@Test
@@ -102,5 +112,29 @@
assertNull(mCache.get(mKey2));
assertEquals(2, mCache.mKeys.size());
+ verify(mEvictionCallback, times(0)).onEntryEvicted(mKey2);
+ }
+
+ @Test
+ public void put_evictionCallback_notCalled() {
+ mCache.put(mKey1, 1);
+ verify(mEvictionCallback, times(0)).onEntryEvicted(mKey1);
+ }
+
+ @Test
+ public void evictAll_evictionCallback_called() {
+ mCache.put(mKey1, 1);
+ mCache.evictAllCache();
+ verify(mEvictionCallback, times(1)).onEntryEvicted(mKey1);
+ }
+
+ @Test
+ public void trimAll_evictionCallback_called() {
+ mCache.put(mKey1, 1);
+ mCache.put(mKey2, 2);
+ mCache.trimToSize(-1);
+ verify(mEvictionCallback, times(1)).onEntryEvicted(mKey1);
+ verify(mEvictionCallback, times(1)).onEntryEvicted(mKey2);
+
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationDataTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationDataTest.java
index 260555f..e2d8e56 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationDataTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationDataTest.java
@@ -23,6 +23,7 @@
import static android.app.Notification.CATEGORY_EVENT;
import static android.app.Notification.CATEGORY_MESSAGE;
import static android.app.Notification.CATEGORY_REMINDER;
+import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
import static android.app.NotificationManager.IMPORTANCE_LOW;
import static android.app.NotificationManager.IMPORTANCE_MIN;
@@ -62,6 +63,8 @@
import android.testing.TestableLooper.RunWithLooper;
import android.util.ArraySet;
+import androidx.test.filters.SmallTest;
+
import com.android.systemui.Dependency;
import com.android.systemui.ForegroundServiceController;
import com.android.systemui.InitController;
@@ -85,8 +88,6 @@
import java.util.List;
import java.util.Map;
-import androidx.test.filters.SmallTest;
-
@SmallTest
@RunWith(AndroidTestingRunner.class)
@RunWithLooper
@@ -114,6 +115,7 @@
MockitoAnnotations.initMocks(this);
when(mMockStatusBarNotification.getUid()).thenReturn(UID_NORMAL);
when(mMockStatusBarNotification.cloneLight()).thenReturn(mMockStatusBarNotification);
+ when(mMockStatusBarNotification.getKey()).thenReturn("mock_key");
when(mMockPackageManager.checkUidPermission(
eq(Manifest.permission.NOTIFICATION_DURING_SETUP),
@@ -232,6 +234,7 @@
Notification n = mMockStatusBarNotification.getNotification();
n.flags = Notification.FLAG_FOREGROUND_SERVICE;
NotificationEntry entry = new NotificationEntry(mMockStatusBarNotification);
+ entry.setRow(mRow);
mNotificationData.add(entry);
Bundle override = new Bundle();
override.putInt(OVERRIDE_VIS_EFFECTS, 255);
@@ -250,6 +253,7 @@
n = nb.build();
when(mMockStatusBarNotification.getNotification()).thenReturn(n);
NotificationEntry entry = new NotificationEntry(mMockStatusBarNotification);
+ entry.setRow(mRow);
mNotificationData.add(entry);
Bundle override = new Bundle();
override.putInt(OVERRIDE_VIS_EFFECTS, 255);
@@ -263,6 +267,7 @@
public void testIsExemptFromDndVisualSuppression_system() {
initStatusBarNotification(false);
NotificationEntry entry = new NotificationEntry(mMockStatusBarNotification);
+ entry.setRow(mRow);
entry.mIsSystemNotification = true;
mNotificationData.add(entry);
Bundle override = new Bundle();
@@ -277,6 +282,7 @@
public void testIsNotExemptFromDndVisualSuppression_hiddenCategories() {
initStatusBarNotification(false);
NotificationEntry entry = new NotificationEntry(mMockStatusBarNotification);
+ entry.setRow(mRow);
entry.mIsSystemNotification = true;
Bundle override = new Bundle();
override.putInt(OVERRIDE_VIS_EFFECTS, NotificationManager.Policy.SUPPRESSED_EFFECT_AMBIENT);
@@ -529,6 +535,62 @@
assertEquals(-1, mNotificationData.mRankingComparator.compare(a, b));
}
+ @Test
+ public void testSort_properlySetsIsTopBucket() {
+
+ Notification notification = new Notification.Builder(mContext, "test")
+ .build();
+ StatusBarNotification sbn = new StatusBarNotification(
+ "pkg",
+ "pkg",
+ 0,
+ "tag",
+ 0,
+ 0,
+ notification,
+ mContext.getUser(),
+ "",
+ 0);
+
+ Bundle override = new Bundle();
+ override.putInt(OVERRIDE_IMPORTANCE, IMPORTANCE_DEFAULT);
+ mNotificationData.rankingOverrides.put(sbn.getKey(), override);
+
+ NotificationEntry entry = new NotificationEntry(sbn);
+ entry.setRow(mRow);
+ mNotificationData.add(entry);
+
+ assertTrue(entry.isTopBucket());
+ }
+
+ @Test
+ public void testSort_properlySetsIsNotTopBucket() {
+ Notification notification = new Notification.Builder(mContext, "test")
+ .build();
+ StatusBarNotification sbn = new StatusBarNotification(
+ "pkg",
+ "pkg",
+ 0,
+ "tag",
+ 0,
+ 0,
+ notification,
+ mContext.getUser(),
+ "",
+ 0);
+
+ Bundle override = new Bundle();
+ override.putInt(OVERRIDE_IMPORTANCE, IMPORTANCE_LOW);
+ mNotificationData.rankingOverrides.put(sbn.getKey(), override);
+
+ NotificationEntry entry = new NotificationEntry(sbn);
+ entry.setRow(mRow);
+
+ mNotificationData.add(entry);
+
+ assertFalse(entry.isTopBucket());
+ }
+
private void initStatusBarNotification(boolean allowDuringSetup) {
Bundle bundle = new Bundle();
bundle.putBoolean(Notification.EXTRA_ALLOW_DURING_SETUP, allowDuringSetup);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
index 0dbf308..97ad47e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
@@ -47,6 +47,7 @@
import com.android.internal.util.function.TriConsumer;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.statusbar.ScrimView;
+import com.android.systemui.statusbar.policy.KeyguardMonitor;
import com.android.systemui.util.wakelock.WakeLock;
import com.android.systemui.utils.os.FakeHandler;
@@ -96,7 +97,8 @@
mScrimBehindAlpha = scrimBehindAlpha;
mScrimInFrontColor = scrimInFrontColor;
},
- visible -> mScrimVisibility = visible, mDozeParamenters, mAlarmManager);
+ visible -> mScrimVisibility = visible, mDozeParamenters, mAlarmManager,
+ mock(KeyguardMonitor.class));
mScrimController.setHasBackdrop(false);
mScrimController.setWallpaperSupportsAmbientMode(false);
mScrimController.transitionTo(ScrimState.KEYGUARD);
@@ -681,9 +683,9 @@
SynchronousScrimController(ScrimView scrimBehind, ScrimView scrimInFront,
TriConsumer<ScrimState, Float, GradientColors> scrimStateListener,
Consumer<Integer> scrimVisibleListener, DozeParameters dozeParameters,
- AlarmManager alarmManager) {
+ AlarmManager alarmManager, KeyguardMonitor keyguardMonitor) {
super(scrimBehind, scrimInFront, scrimStateListener, scrimVisibleListener,
- dozeParameters, alarmManager);
+ dozeParameters, alarmManager, keyguardMonitor);
}
@Override
diff --git a/packages/VpnDialogs/res/values-hi/strings.xml b/packages/VpnDialogs/res/values-hi/strings.xml
index 34b79cb..eed0858 100644
--- a/packages/VpnDialogs/res/values-hi/strings.xml
+++ b/packages/VpnDialogs/res/values-hi/strings.xml
@@ -22,7 +22,7 @@
<string name="session" msgid="6470628549473641030">"सत्र:"</string>
<string name="duration" msgid="3584782459928719435">"अवधि:"</string>
<string name="data_transmitted" msgid="7988167672982199061">"भेजे गए:"</string>
- <string name="data_received" msgid="4062776929376067820">"प्राप्त:"</string>
+ <string name="data_received" msgid="4062776929376067820">"पाया:"</string>
<string name="data_value_format" msgid="2192466557826897580">"<xliff:g id="NUMBER_0">%1$s</xliff:g> बाइट / <xliff:g id="NUMBER_1">%2$s</xliff:g> पैकेट"</string>
<string name="always_on_disconnected_title" msgid="1906740176262776166">"हमेशा चालू रहने वाले VPN से नहीं जुड़ पा रहा है"</string>
<string name="always_on_disconnected_message" msgid="555634519845992917">"<xliff:g id="VPN_APP_0">%1$s</xliff:g> को हर समय जुड़े रहने के लिए सेट अप किया गया है, लेकिन वह इस समय नहीं जुड़ पा रहा है. जब तक आपका फ़ोन <xliff:g id="VPN_APP_1">%1$s</xliff:g> से नहीं जुड़ जाता, तब तक वह सार्वजनिक नेटवर्क का इस्तेमाल करेगा."</string>
diff --git a/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java b/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java
index 10c32ee..d8b7e3a 100644
--- a/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java
+++ b/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java
@@ -27,8 +27,6 @@
import android.util.Slog;
import android.view.InputDevice;
import android.view.MotionEvent;
-import android.view.MotionEvent.PointerCoords;
-import android.view.MotionEvent.PointerProperties;
import android.view.ViewConfiguration;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
@@ -129,15 +127,6 @@
// Context in which this explorer operates.
private final Context mContext;
- // The long pressing pointer id if coordinate remapping is needed.
- private int mLongPressingPointerId = -1;
-
- // The long pressing pointer X if coordinate remapping is needed.
- private int mLongPressingPointerDeltaX;
-
- // The long pressing pointer Y if coordinate remapping is needed.
- private int mLongPressingPointerDeltaY;
-
/**
* Creates a new instance.
@@ -231,10 +220,6 @@
mGestureDetector.clear();
// Go to initial state.
mState.clear();
- // Clear the long pressing pointer remap data.
- mLongPressingPointerId = -1;
- mLongPressingPointerDeltaX = 0;
- mLongPressingPointerDeltaY = 0;
mAms.onTouchInteractionEnd();
}
@@ -705,17 +690,6 @@
return;
}
case MotionEvent.ACTION_UP: {
- // Offset the event if we are doing a long press as the
- // target is not necessarily under the user's finger.
- if (mLongPressingPointerId >= 0) {
- event = offsetEvent(event, - mLongPressingPointerDeltaX,
- - mLongPressingPointerDeltaY);
- // Clear the long press state.
- mLongPressingPointerId = -1;
- mLongPressingPointerDeltaX = 0;
- mLongPressingPointerDeltaY = 0;
- }
-
// Deliver the event.
sendMotionEvent(event, event.getAction(), ALL_POINTER_ID_BITS, policyFlags);
@@ -865,18 +839,6 @@
} else {
event.setDownTime(mInjectedPointerTracker.getLastInjectedDownEventTime());
}
-
- // If the user is long pressing but the long pressing pointer
- // was not exactly over the accessibility focused item we need
- // to remap the location of that pointer so the user does not
- // have to explicitly touch explore something to be able to
- // long press it, or even worse to avoid the user long pressing
- // on the wrong item since click and long press behave differently.
- if (mLongPressingPointerId >= 0) {
- event = offsetEvent(event, - mLongPressingPointerDeltaX,
- - mLongPressingPointerDeltaY);
- }
-
if (DEBUG) {
Slog.d(LOG_TAG, "Injecting event: " + event + ", policyFlags=0x"
+ Integer.toHexString(policyFlags));
@@ -897,39 +859,6 @@
}
/**
- * Offsets all pointers in the given event by adding the specified X and Y
- * offsets.
- *
- * @param event The event to offset.
- * @param offsetX The X offset.
- * @param offsetY The Y offset.
- * @return An event with the offset pointers or the original event if both
- * offsets are zero.
- */
- private MotionEvent offsetEvent(MotionEvent event, int offsetX, int offsetY) {
- if (offsetX == 0 && offsetY == 0) {
- return event;
- }
- final int remappedIndex = event.findPointerIndex(mLongPressingPointerId);
- final int pointerCount = event.getPointerCount();
- PointerProperties[] props = PointerProperties.createArray(pointerCount);
- PointerCoords[] coords = PointerCoords.createArray(pointerCount);
- for (int i = 0; i < pointerCount; i++) {
- event.getPointerProperties(i, props[i]);
- event.getPointerCoords(i, coords[i]);
- if (i == remappedIndex) {
- coords[i].x += offsetX;
- coords[i].y += offsetY;
- }
- }
- return MotionEvent.obtain(event.getDownTime(),
- event.getEventTime(), event.getAction(), event.getPointerCount(),
- props, coords, event.getMetaState(), event.getButtonState(),
- 1.0f, 1.0f, event.getDeviceId(), event.getEdgeFlags(),
- event.getSource(), event.getDisplayId(), event.getFlags());
- }
-
- /**
* Computes the action for an injected event based on a masked action
* and a pointer index.
*
@@ -1189,9 +1118,6 @@
+ ", mDetermineUserIntentTimeout: " + mDetermineUserIntentTimeout
+ ", mDoubleTapSlop: " + mDoubleTapSlop
+ ", mDraggingPointerId: " + mDraggingPointerId
- + ", mLongPressingPointerId: " + mLongPressingPointerId
- + ", mLongPressingPointerDeltaX: " + mLongPressingPointerDeltaX
- + ", mLongPressingPointerDeltaY: " + mLongPressingPointerDeltaY
+ ", mTempPoint: " + mTempPoint
+ " }";
}
diff --git a/services/art-profile-boot b/services/art-profile-boot
index 23d7090..e09424b 100644
--- a/services/art-profile-boot
+++ b/services/art-profile-boot
@@ -1,326 +1,760 @@
-Lcom/android/server/SystemServer;->run()V
-Lcom/android/server/SystemServer;->main([Ljava/lang/String;)V
-Lcom/android/server/SystemServer;->startBootstrapServices()V
-Lcom/android/server/pm/PackageManagerService;->main(Landroid/content/Context;Lcom/android/server/pm/Installer;ZZ)Lcom/android/server/pm/PackageManagerService;
-Lcom/android/server/pm/PackageManagerService;-><init>(Landroid/content/Context;Lcom/android/server/pm/Installer;ZZ)V
-Lcom/android/server/pm/Settings;->readLPw(Ljava/util/List;)Z
-Lcom/android/server/pm/Settings;->readPackageLPw(Lorg/xmlpull/v1/XmlPullParser;)V
-Lcom/android/server/pm/Settings;->readInstallPermissionsLPr(Lorg/xmlpull/v1/XmlPullParser;Lcom/android/server/pm/permission/PermissionsState;)V
-Lcom/android/server/pm/permission/PermissionsState;->grantPermission(Lcom/android/server/pm/permission/BasePermission;I)I
-Lcom/android/server/pm/permission/PermissionsState;->grantInstallPermission(Lcom/android/server/pm/permission/BasePermission;)I
-Lcom/android/server/-$$Lambda$YWiwiKm_Qgqb55C6tTuq_n2JzdY;->run()V
-Lcom/android/server/pm/PackageSignatures;->readXml(Lorg/xmlpull/v1/XmlPullParser;Ljava/util/ArrayList;)V
-Lcom/android/server/pm/permission/PermissionsState;->computeGids(I)[I
-Lcom/android/server/am/-$$Lambda$BatteryExternalStatsWorker$ddVY5lmqswnSjXppAxPTOHbuzzQ;->run()V
-Lcom/android/server/SystemServiceManager;->startService(Lcom/android/server/SystemService;)V
-Lcom/android/server/SystemServiceManager;->startService(Ljava/lang/Class;)Lcom/android/server/SystemService;
-Lcom/android/server/SystemServiceManager;->startService(Ljava/lang/String;)Lcom/android/server/SystemService;
-Lcom/android/server/pm/permission/PermissionsState;->hasPermission(Ljava/lang/String;I)Z
-Lcom/android/server/pm/permission/PermissionsState;->hasPermissionRequiringReview(I)Z
-Lcom/android/server/am/ActivityManagerService$Lifecycle;-><init>(Landroid/content/Context;)V
-Lcom/android/server/am/ActivityManagerService;-><init>(Landroid/content/Context;Lcom/android/server/wm/ActivityTaskManagerService;)V
-Lcom/android/server/pm/Settings;->readSharedUserLPw(Lorg/xmlpull/v1/XmlPullParser;)V
-Lcom/android/server/pm/permission/PermissionsState;->updatePermissionFlags(Lcom/android/server/pm/permission/BasePermission;III)Z
-Lcom/android/server/pm/permission/PermissionsState;->ensurePermissionData(Lcom/android/server/pm/permission/BasePermission;)Lcom/android/server/pm/permission/PermissionsState$PermissionData;
-Lcom/android/server/am/BatteryExternalStatsWorker$1;->run()V
-Lcom/android/server/am/BatteryExternalStatsWorker;->updateExternalStatsLocked(Ljava/lang/String;IZZZ)V
-Lcom/android/server/pm/permission/PermissionsState$PermissionData;->grant(I)Z
-Lcom/android/server/am/BatteryExternalStatsWorker$2;->run()V
-Lcom/android/server/pm/permission/PermissionSettings;->getPermission(Ljava/lang/String;)Lcom/android/server/pm/permission/BasePermission;
-Lcom/android/server/pm/permission/PermissionSettings;->getPermissionLocked(Ljava/lang/String;)Lcom/android/server/pm/permission/BasePermission;
-Lcom/android/server/pm/permission/PermissionSettings;->getPermissionTreeLocked(Ljava/lang/String;)Lcom/android/server/pm/permission/BasePermission;
-Lcom/android/server/pm/Settings;->readDisabledSysPackageLPw(Lorg/xmlpull/v1/XmlPullParser;)V
-Lcom/android/server/pm/permission/PermissionsState$PermissionData;->updateFlags(III)Z
-Lcom/android/server/pm/PackageSignatures;->readCertsListXml(Lorg/xmlpull/v1/XmlPullParser;Ljava/util/ArrayList;Ljava/util/ArrayList;IZLandroid/content/pm/PackageParser$SigningDetails$Builder;)I
-Lcom/android/server/pm/permission/PermissionsState$PermissionData;-><init>(Lcom/android/server/pm/permission/PermissionsState$PermissionData;)V
-Lcom/android/server/pm/permission/PermissionSettings;->readPermissions(Landroid/util/ArrayMap;Lorg/xmlpull/v1/XmlPullParser;)V
-Lcom/android/server/pm/permission/PermissionSettings;->readPermissions(Lorg/xmlpull/v1/XmlPullParser;)V
-Lcom/android/server/pm/Settings$RuntimePermissionPersistence;->readStateForUserSyncLPr(I)V
-Lcom/android/server/pm/Settings$RuntimePermissionPersistence;->parseRuntimePermissionsLPr(Lorg/xmlpull/v1/XmlPullParser;I)V
-Lcom/android/server/pm/Settings$RuntimePermissionPersistence;->parsePermissionsLPr(Lorg/xmlpull/v1/XmlPullParser;Lcom/android/server/pm/permission/PermissionsState;I)V
-Lcom/android/server/pm/permission/BasePermission;->readLPw(Ljava/util/Map;Lorg/xmlpull/v1/XmlPullParser;)Z
-Lcom/android/server/pm/Settings;->writeKernelMappingLPr()V
-Lcom/android/server/pm/Settings;->writeKernelMappingLPr(Lcom/android/server/pm/PackageSetting;)V
-Lcom/android/server/pm/Settings;->writeKernelMappingLPr(Ljava/lang/String;I[I)V
-Lcom/android/server/pm/Settings;->readPackageRestrictionsLPr(I)V
-Lcom/android/server/am/ActivityManagerService$Injector;->getAppOpsService(Ljava/io/File;Landroid/os/Handler;)Lcom/android/server/appop/AppOpsService;
-Lcom/android/server/appop/AppOpsService;-><init>(Ljava/io/File;Landroid/os/Handler;)V
-Lcom/android/server/appop/AppOpsService;->readState()V
-Lcom/android/server/am/ProcessStatsService;-><init>(Lcom/android/server/am/ActivityManagerService;Ljava/io/File;)V
-Lcom/android/server/pm/PackageManagerService;->scanDirTracedLI(Ljava/io/File;IIJ)V
-Lcom/android/server/pm/PackageManagerService;->scanDirLI(Ljava/io/File;IIJ)V
-Lcom/android/server/pm/PackageManagerService;->addForInitLI(Landroid/content/pm/PackageParser$Package;IIJLandroid/os/UserHandle;)Landroid/content/pm/PackageParser$Package;
-Lcom/android/server/pm/PackageManagerService;->scanPackageChildLI(Landroid/content/pm/PackageParser$Package;IIJLandroid/os/UserHandle;)Landroid/content/pm/PackageParser$Package;
-Lcom/android/server/pm/KeySetManagerService;->readKeySetsLPw(Lorg/xmlpull/v1/XmlPullParser;Landroid/util/ArrayMap;)V
-Lcom/android/server/pm/ParallelPackageParser;->lambda$submit$0$ParallelPackageParser(Ljava/io/File;I)V
-Lcom/android/server/pm/-$$Lambda$ParallelPackageParser$FTtinPrp068lVeI7K6bC1tNE3iM;->run()V
-Lcom/android/server/pm/ParallelPackageParser;->parsePackage(Landroid/content/pm/PackageParser;Ljava/io/File;I)Landroid/content/pm/PackageParser$Package;
-Lcom/android/server/appop/AppOpsService;->readPackage(Lorg/xmlpull/v1/XmlPullParser;)V
-Lcom/android/server/pm/Settings;->addPackageLPw(Ljava/lang/String;Ljava/lang/String;Ljava/io/File;Ljava/io/File;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;IJIILjava/lang/String;Ljava/util/List;[Ljava/lang/String;[J)Lcom/android/server/pm/PackageSetting;
-Lcom/android/server/appop/AppOpsService;->readUid(Lorg/xmlpull/v1/XmlPullParser;Ljava/lang/String;)V
Lcom/android/server/appop/AppOpsService;->readUidOps(Lorg/xmlpull/v1/XmlPullParser;)V
-Lcom/android/server/pm/PackageSetting;-><init>(Lcom/android/server/pm/PackageSetting;)V
-Lcom/android/server/pm/PackageSetting;-><init>(Ljava/lang/String;Ljava/lang/String;Ljava/io/File;Ljava/io/File;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;JIILjava/lang/String;Ljava/util/List;I[Ljava/lang/String;[J)V
-Lcom/android/server/pm/SELinuxMMAC;->readInstallPolicy()Z
-Lcom/android/server/pm/KeySetManagerService;->readKeysLPw(Lorg/xmlpull/v1/XmlPullParser;)V
-Lcom/android/server/pm/Settings;->writeIntToFile(Ljava/io/File;I)V
-Lcom/android/server/pm/PackageSettingBase;-><init>(Ljava/lang/String;Ljava/lang/String;Ljava/io/File;Ljava/io/File;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;JIILjava/lang/String;Ljava/util/List;[Ljava/lang/String;[J)V
Lcom/android/server/appop/AppOpsService;->readOp(Lorg/xmlpull/v1/XmlPullParser;Lcom/android/server/appop/AppOpsService$UidState;Ljava/lang/String;Z)V
-Lcom/android/server/pm/SELinuxMMAC;->readSignerOrThrow(Lorg/xmlpull/v1/XmlPullParser;)Lcom/android/server/pm/Policy;
-Lcom/android/server/pm/Settings;->readComponentsLPr(Lorg/xmlpull/v1/XmlPullParser;)Landroid/util/ArraySet;
-Lcom/android/server/pm/KeySetManagerService;->readPublicKeyLPw(Lorg/xmlpull/v1/XmlPullParser;)V
-Lcom/android/server/pm/PackageManagerService;->scanPackageNewLI(Landroid/content/pm/PackageParser$Package;IIJLandroid/os/UserHandle;)Lcom/android/server/pm/PackageManagerService$ScanResult;
-Lcom/android/server/pm/permission/PermissionsState;->grantRuntimePermission(Lcom/android/server/pm/permission/BasePermission;I)I
-Lcom/android/server/pm/Policy$PolicyBuilder;->addSignature(Ljava/lang/String;)Lcom/android/server/pm/Policy$PolicyBuilder;
-Lcom/android/server/display/DisplayManagerService;-><init>(Landroid/content/Context;)V
-Lcom/android/server/display/DisplayManagerService;-><init>(Landroid/content/Context;Lcom/android/server/display/DisplayManagerService$Injector;)V
-Lcom/android/server/am/ActivityManagerService;->start()V
-Lcom/android/server/am/ActivityManagerService;->startAssociationLocked(ILjava/lang/String;IIJLandroid/content/ComponentName;Ljava/lang/String;)Lcom/android/server/am/ActivityManagerService$Association;
-Lcom/android/server/am/ActivityManagerService;->startIsolatedProcess(Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILjava/lang/Runnable;)Z
-Lcom/android/server/am/ActivityManagerService;->startObservingNativeCrashes()V
-Lcom/android/server/am/ActivityManagerService;->startPersistentApps(I)V
-Lcom/android/server/am/ActivityManagerService;->startProcessLocked(Ljava/lang/String;Landroid/content/pm/ApplicationInfo;ZILjava/lang/String;Landroid/content/ComponentName;ZZZ)Lcom/android/server/am/ProcessRecord;
-Lcom/android/server/am/ActivityManagerService;->startService(Landroid/app/IApplicationThread;Landroid/content/Intent;Ljava/lang/String;ZLjava/lang/String;I)Landroid/content/ComponentName;
-PLcom/android/server/am/ActivityManagerService;->startUserInBackgroundWithListener(ILandroid/os/IProgressListener;)Z
-Lcom/android/server/am/ActivityManagerService$Lifecycle;->onStart()V
-Lcom/android/server/pm/PackageManagerService;->scanPackageOnlyLI(Lcom/android/server/pm/PackageManagerService$ScanRequest;ZJ)Lcom/android/server/pm/PackageManagerService$ScanResult;
-Lcom/android/server/pm/PackageSettingBase;->modifyUserState(I)Landroid/content/pm/PackageUserState;
-Lcom/android/server/pm/PackageSettingBase;->modifyUserStateComponents(IZZ)Landroid/content/pm/PackageUserState;
-Lcom/android/server/pm/Settings;->readDomainVerificationLPw(Lorg/xmlpull/v1/XmlPullParser;Lcom/android/server/pm/PackageSettingBase;)V
-Lcom/android/server/pm/PackageSettingBase;->setEnabled(IILjava/lang/String;)V
-Lcom/android/server/am/BatteryStatsService;-><init>(Landroid/content/Context;Ljava/io/File;Landroid/os/Handler;)V
-Lcom/android/server/pm/PackageManagerService;->commitReconciledScanResultLocked(Lcom/android/server/pm/PackageManagerService$ReconciledPackage;)V
-Lcom/android/server/pm/KeySetManagerService;->readKeySetListLPw(Lorg/xmlpull/v1/XmlPullParser;)V
-Lcom/android/server/appop/AppOpsService$Op;->accessed(JILjava/lang/String;II)V
-Lcom/android/server/wm/ActivityTaskManagerService;->initialize(Lcom/android/server/firewall/IntentFirewall;Lcom/android/server/am/PendingIntentController;Landroid/os/Looper;)V
-Lcom/android/server/pm/SettingBase;-><init>(II)V
-Lcom/android/server/pm/PackageManagerService;->locationIsPrivileged(Ljava/lang/String;)Z
-Lcom/android/server/power/PowerManagerService;-><init>(Landroid/content/Context;)V
-Lcom/android/server/power/PowerManagerService;-><init>(Landroid/content/Context;Lcom/android/server/power/PowerManagerService$Injector;)V
-Lcom/android/server/pm/permission/PermissionsState;->enforceValidUserId(I)V
-Lcom/android/server/Watchdog;->getInstance()Lcom/android/server/Watchdog;
-Lcom/android/server/Watchdog;-><init>()V
-Lcom/android/server/pm/PackageManagerService;->commitPackageSettings(Landroid/content/pm/PackageParser$Package;Landroid/content/pm/PackageParser$Package;Lcom/android/server/pm/PackageSetting;IZLcom/android/server/pm/PackageManagerService$ReconciledPackage;)V
-Lcom/android/server/pm/PackageSetting;->getPermissionsState()Lcom/android/server/pm/permission/PermissionsState;
-Lcom/android/server/pm/Settings;->registerExistingAppIdLPw(ILcom/android/server/pm/SettingBase;Ljava/lang/Object;)Z
-Lcom/android/server/pm/permission/PermissionManagerService;->create(Landroid/content/Context;Lcom/android/server/pm/permission/DefaultPermissionGrantPolicy$DefaultPermissionGrantedCallback;Ljava/lang/Object;)Lcom/android/server/pm/permission/PermissionManagerServiceInternal;
-Lcom/android/server/pm/Settings;->addSharedUserLPw(Ljava/lang/String;III)Lcom/android/server/pm/SharedUserSetting;
-Lcom/android/server/pm/PackageSettingBase;->init(Ljava/io/File;Ljava/io/File;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;J)V
-Lcom/android/server/appop/AppOpsService$Op;->updateProxyState(JILjava/lang/String;)V
-Lcom/android/server/display/DisplayManagerService$DisplayAdapterListener;->onDisplayDeviceEvent(Lcom/android/server/display/DisplayDevice;I)V
-Lcom/android/server/wm/ActivityTaskManagerService;->onActivityManagerInternalAdded()V
-Lcom/android/server/SystemService;->publishBinderService(Ljava/lang/String;Landroid/os/IBinder;)V
-Lcom/android/server/am/ActivityManagerService;->initPowerManagement()V
-Lcom/android/server/wm/ActivityTaskManagerService$Lifecycle;-><init>(Landroid/content/Context;)V
-Lcom/android/server/display/DisplayManagerService;->onStart()V
-Lcom/android/server/pm/Settings;->readPreferredActivitiesLPw(Lorg/xmlpull/v1/XmlPullParser;I)V
-Lcom/android/server/pm/PackageKeySetData;-><init>()V
-Lcom/android/server/display/DisplayManagerService;->registerDefaultDisplayAdapters()V
-Lcom/android/server/display/LocalDisplayAdapter;->registerLocked()V
-Lcom/android/server/ServiceThread;->run()V
-Lcom/android/server/display/DisplayModeDirector;-><init>(Landroid/content/Context;Landroid/os/Handler;)V
-Lcom/android/server/pm/Settings;->addPackageSettingLPw(Lcom/android/server/pm/PackageSetting;Lcom/android/server/pm/SharedUserSetting;)V
-Lcom/android/server/pm/permission/PermissionManagerService;-><init>(Landroid/content/Context;Lcom/android/server/pm/permission/DefaultPermissionGrantPolicy$DefaultPermissionGrantedCallback;Ljava/lang/Object;)V
-Lcom/android/server/appop/AppOpsService;->getUidStateLocked(IZ)Lcom/android/server/appop/AppOpsService$UidState;
-Lcom/android/server/am/BatteryStatsService;->fillRailDataStats(Lcom/android/internal/os/RailStats;)V
-Lcom/android/server/pm/SELinuxMMAC;->getSeInfo(Landroid/content/pm/PackageParser$Package;ZII)Ljava/lang/String;
-Lcom/android/server/pm/PackageManagerService;->collectCertificatesLI(Lcom/android/server/pm/PackageSetting;Landroid/content/pm/PackageParser$Package;ZZ)V
-Lcom/android/server/pm/PackageManagerService;->reconcilePackagesLocked(Lcom/android/server/pm/PackageManagerService$ReconcileRequest;Lcom/android/server/pm/KeySetManagerService;)Ljava/util/Map;
-Lcom/android/server/pm/permission/BasePermission;->readInt(Lorg/xmlpull/v1/XmlPullParser;Ljava/lang/String;Ljava/lang/String;I)I
-Lcom/android/server/pm/UserManagerService;-><init>(Landroid/content/Context;Lcom/android/server/pm/PackageManagerService;Lcom/android/server/pm/UserDataPreparer;Ljava/lang/Object;)V
-Lcom/android/server/pm/UserManagerService;-><init>(Landroid/content/Context;Lcom/android/server/pm/PackageManagerService;Lcom/android/server/pm/UserDataPreparer;Ljava/lang/Object;Ljava/io/File;)V
-Lcom/android/server/display/LocalDisplayAdapter;->tryConnectDisplayLocked(J)V
-Lcom/android/server/pm/PreferredActivity;-><init>(Landroid/content/IntentFilter;I[Landroid/content/ComponentName;Landroid/content/ComponentName;Z)V
-Lcom/android/server/pm/PackageManagerService;->preparePackageParserCache()Ljava/io/File;
-Lcom/android/server/pm/Policy$PolicyBuilder;->build()Lcom/android/server/pm/Policy;
-Lcom/android/server/LockGuard;->installLock(Ljava/lang/Object;I)Ljava/lang/Object;
-Lcom/android/server/LockGuard;->installLock(Ljava/lang/Object;IZ)Ljava/lang/Object;
-Lcom/android/server/SystemServiceManager;->startBootPhase(I)V
-Lcom/android/server/display/PersistentDataStore;->load()V
-Lcom/android/server/display/PersistentDataStore;->loadDisplaysFromXml(Lorg/xmlpull/v1/XmlPullParser;)V
-Lcom/android/server/display/PersistentDataStore;->loadFromXml(Lorg/xmlpull/v1/XmlPullParser;)V
-Lcom/android/server/display/PersistentDataStore;->loadRememberedWifiDisplaysFromXml(Lorg/xmlpull/v1/XmlPullParser;)V
-Lcom/android/server/wm/AppWarnings;-><init>(Lcom/android/server/wm/ActivityTaskManagerService;Landroid/content/Context;Landroid/os/Handler;Landroid/os/Handler;Ljava/io/File;)V
-Lcom/android/server/pm/PreferredComponent;-><init>(Lcom/android/server/pm/PreferredComponent$Callbacks;I[Landroid/content/ComponentName;Landroid/content/ComponentName;Z)V
-Lcom/android/server/pm/PreferredComponent;-><init>(Lcom/android/server/pm/PreferredComponent$Callbacks;Lorg/xmlpull/v1/XmlPullParser;)V
-Lcom/android/server/display/DisplayManagerService;->handleDisplayDeviceAdded(Lcom/android/server/display/DisplayDevice;)V
-Lcom/android/server/display/DisplayManagerService;->handleDisplayDeviceAddedLocked(Lcom/android/server/display/DisplayDevice;)V
-Lcom/android/server/display/LocalDisplayAdapter$LocalDisplayDevice;->getDisplayDeviceInfoLocked()Lcom/android/server/display/DisplayDeviceInfo;
-Lcom/android/server/pm/PackageSettingBase;->setUserState(IJIZZZZIZLjava/lang/String;Landroid/content/pm/SuspendDialogInfo;Landroid/os/PersistableBundle;Landroid/os/PersistableBundle;ZZLjava/lang/String;Landroid/util/ArraySet;Landroid/util/ArraySet;IIILjava/lang/String;)V
-Lcom/android/server/pm/Installer;->onStart()V
-Lcom/android/server/pm/Installer;->connect()V
-Lcom/android/server/lights/LightsService$LightImpl;-><init>(Lcom/android/server/lights/LightsService;Landroid/content/Context;I)V
-Lcom/android/server/pm/PackageManagerService;->addBuiltInSharedLibraryLocked(Ljava/lang/String;Ljava/lang/String;)Z
-Lcom/android/server/LockGuard;->findOrCreateLockInfo(Ljava/lang/Object;)Lcom/android/server/LockGuard$LockInfo;
-Lcom/android/server/lights/LightsService;-><init>(Landroid/content/Context;)V
-Lcom/android/server/pm/Policy;->getMatchedSeInfo(Landroid/content/pm/PackageParser$Package;)Ljava/lang/String;
-Lcom/android/server/ServiceThread;-><init>(Ljava/lang/String;IZ)V
-Lcom/android/server/wm/ActivityTaskManagerService;->createStackSupervisor()Lcom/android/server/wm/ActivityStackSupervisor;
-Lcom/android/server/Watchdog;->addMonitor(Lcom/android/server/Watchdog$Monitor;)V
-Lcom/android/server/wm/ActivityStackSupervisor;->initPowerManagement()V
-Lcom/android/server/wm/ActivityTaskManagerService;->onInitPowerManagement()V
-Lcom/android/server/pm/KeySetManagerService;->addScannedPackageLPw(Landroid/content/pm/PackageParser$Package;)V
-Lcom/android/server/am/BatteryStatsService;->initPowerManagement()V
-Lcom/android/server/wm/ActivityTaskManagerService;-><init>(Landroid/content/Context;)V
-Lcom/android/server/am/ProcessList;-><init>()V
-Lcom/android/server/pm/PackageManagerService;->commitSharedLibraryInfoLocked(Landroid/content/pm/SharedLibraryInfo;)V
-Lcom/android/server/pm/PackageManagerServiceUtils;->getLastModifiedTime(Landroid/content/pm/PackageParser$Package;)J
-Lcom/android/server/am/ProcessStatsService;->updateFile()V
-Lcom/android/server/pm/Policy$PolicyBuilder;->setGlobalSeinfoOrThrow(Ljava/lang/String;)Lcom/android/server/pm/Policy$PolicyBuilder;
-Lcom/android/server/wm/AppWarnings;->readConfigFromFileAmsThread()V
-Lcom/android/server/am/BatteryStatsService;->fillLowPowerStats(Lcom/android/internal/os/RpmStats;)V
-Lcom/android/server/display/DisplayManagerService;->handleDisplayDeviceChanged(Lcom/android/server/display/DisplayDevice;)V
-Lcom/android/server/firewall/IntentFirewall;-><init>(Lcom/android/server/firewall/IntentFirewall$AMSInterface;Landroid/os/Handler;)V
-Lcom/android/server/pm/PackageSettingBase;->getNotInstalledUserIds()[I
Lcom/android/server/appop/AppOpsService$UidState;->evalForegroundOps(Landroid/util/SparseArray;)V
-Lcom/android/server/SystemServerInitThreadPool;->submit(Ljava/lang/Runnable;Ljava/lang/String;)Ljava/util/concurrent/Future;
-Lcom/android/server/pm/KeySetManagerService;->addSigningKeySetToPackageLPw(Lcom/android/server/pm/PackageSetting;Landroid/util/ArraySet;)V
-Lcom/android/server/pm/ComponentResolver;->addAllComponents(Landroid/content/pm/PackageParser$Package;Z)V
-Lcom/android/server/appop/AppOpsService;->publish(Landroid/content/Context;)V
-Lcom/android/server/power/PowerManagerService;->onStart()V
-Lcom/android/server/os/DeviceIdentifiersPolicyService;->onStart()V
-Lcom/android/server/uri/UriGrantsManagerService$Lifecycle;-><init>(Landroid/content/Context;)V
-Lcom/android/server/pm/PackageManagerService;->applyPolicy(Landroid/content/pm/PackageParser$Package;IILandroid/content/pm/PackageParser$Package;)V
-Lcom/android/server/pm/KeySetManagerService;->addRefCountsFromSavedPackagesLPw(Landroid/util/ArrayMap;)V
-Lcom/android/server/am/OomAdjuster;-><init>(Lcom/android/server/am/ActivityManagerService;Lcom/android/server/am/ProcessList;Lcom/android/server/am/ActiveUids;)V
-Lcom/android/server/am/ProcessList;->init(Lcom/android/server/am/ActivityManagerService;Lcom/android/server/am/ActiveUids;)V
-Lcom/android/server/pm/PackageManagerService$ScanRequest;-><init>(Landroid/content/pm/PackageParser$Package;Lcom/android/server/pm/SharedUserSetting;Landroid/content/pm/PackageParser$Package;Lcom/android/server/pm/PackageSetting;Lcom/android/server/pm/PackageSetting;Lcom/android/server/pm/PackageSetting;Ljava/lang/String;IIZLandroid/os/UserHandle;)V
-Lcom/android/server/pm/Settings;->writeUserRestrictionsLPw(Lcom/android/server/pm/PackageSetting;Lcom/android/server/pm/PackageSetting;)V
-PLcom/android/server/pm/permission/PermissionsState;-><init>(Lcom/android/server/pm/permission/PermissionsState;)V
-Lcom/android/server/pm/UserManagerService;->readUserListLP()V
-Lcom/android/server/RescueParty;->isUsbActive()Z
-Lcom/android/server/RescueParty;->isDisabled()Z
-Lcom/android/server/pm/SharedUserSetting;->addPackage(Lcom/android/server/pm/PackageSetting;)V
-Lcom/android/server/display/LocalDisplayAdapter$LocalDisplayDevice;-><init>(Lcom/android/server/display/LocalDisplayAdapter;Landroid/os/IBinder;J[Landroid/view/SurfaceControl$PhysicalDisplayInfo;I[I[IIZ)V
-Lcom/android/server/am/BatteryStatsService$WakeupReasonThread;->run()V
-Lcom/android/server/pm/PackageSettingBase;->doCopy(Lcom/android/server/pm/PackageSettingBase;)V
-Lcom/android/server/SystemServerInitThreadPool;->get()Lcom/android/server/SystemServerInitThreadPool;
-Lcom/android/server/pm/PreferredActivity;->onReadTag(Ljava/lang/String;Lorg/xmlpull/v1/XmlPullParser;)Z
-Lcom/android/server/FgThread;->getHandler()Landroid/os/Handler;
-Lcom/android/server/FgThread;->ensureThreadLocked()V
-Lcom/android/server/IntentResolver;->addFilter(Landroid/content/IntentFilter;)V
-Lcom/android/server/IntentResolver;->addFilter(Landroid/util/ArrayMap;Ljava/lang/String;Landroid/content/IntentFilter;)V
-Lcom/android/server/pm/PackageManagerService;->assertPackageIsValid(Landroid/content/pm/PackageParser$Package;II)V
-Lcom/android/server/pm/PackageManagerService;->getSettingsVersionForPackage(Landroid/content/pm/PackageParser$Package;)Lcom/android/server/pm/Settings$VersionInfo;
-Lcom/android/server/pm/KeySetManagerService;->getPublicKeysFromKeySetLPr(J)Landroid/util/ArraySet;
-Lcom/android/server/pm/ComponentResolver;->addActivitiesLocked(Landroid/content/pm/PackageParser$Package;Ljava/util/List;Z)V
-Lcom/android/server/pm/PackageManagerServiceCompilerMapping;->checkProperties()V
-Lcom/android/server/pm/Settings;->getSettingLPr(I)Lcom/android/server/pm/SettingBase;
-Lcom/android/server/uri/UriGrantsManagerService;-><init>(Landroid/content/Context;)V
-Lcom/android/server/pm/Settings;-><init>(Ljava/io/File;Lcom/android/server/pm/permission/PermissionSettings;Ljava/lang/Object;)V
-Lcom/android/server/uri/UriGrantsManagerService$Lifecycle;->onStart()V
-Lcom/android/server/wm/ActivityTaskManagerService$Lifecycle;->onStart()V
-Lcom/android/server/pm/PackageSetting;->updateFrom(Lcom/android/server/pm/PackageSetting;)V
-Lcom/android/server/display/DisplayModeDirector$SettingsObserver;-><init>(Lcom/android/server/display/DisplayModeDirector;Landroid/content/Context;Landroid/os/Handler;)V
-Lcom/android/server/power/batterysaver/BatterySaverController;-><init>(Ljava/lang/Object;Landroid/content/Context;Landroid/os/Looper;Lcom/android/server/power/batterysaver/BatterySaverPolicy;Lcom/android/server/power/batterysaver/BatterySavingStats;)V
-Lcom/android/server/wm/ActivityStackSupervisor;-><init>(Lcom/android/server/wm/ActivityTaskManagerService;Landroid/os/Looper;)V
-Lcom/android/server/PackageWatchdog;-><init>(Landroid/content/Context;)V
-Lcom/android/server/PackageWatchdog;->getInstance(Landroid/content/Context;)Lcom/android/server/PackageWatchdog;
-Lcom/android/server/pm/Settings;->getAllUsers(Lcom/android/server/pm/UserManagerService;)Ljava/util/List;
-Lcom/android/server/Watchdog;->addThread(Landroid/os/Handler;)V
-Lcom/android/server/Watchdog;->addThread(Landroid/os/Handler;J)V
-Lcom/android/server/wm/RecentTasks;-><init>(Lcom/android/server/wm/ActivityTaskManagerService;Lcom/android/server/wm/ActivityStackSupervisor;)V
-Lcom/android/server/pm/PackageSettingBase;->updateFrom(Lcom/android/server/pm/PackageSettingBase;)Lcom/android/server/pm/PackageSettingBase;
-Lcom/android/server/pm/UserManagerService;->getUsers(Z)Ljava/util/List;
-Lcom/android/server/firewall/IntentFirewall;->readRulesDir(Ljava/io/File;)V
-Lcom/android/server/wm/TaskChangeNotificationController;-><init>(Ljava/lang/Object;Lcom/android/server/wm/ActivityStackSupervisor;Landroid/os/Handler;)V
-Lcom/android/server/am/BatteryExternalStatsWorker;->awaitControllerInfo(Landroid/os/SynchronousResultReceiver;)Landroid/os/Parcelable;
-Lcom/android/server/display/DisplayManagerService;->addLogicalDisplayLocked(Lcom/android/server/display/DisplayDevice;)Lcom/android/server/display/LogicalDisplay;
-Lcom/android/server/display/DisplayManagerService;->updateLogicalDisplaysLocked()Z
-Lcom/android/server/display/LocalDisplayAdapter$LocalDisplayDevice;->updatePhysicalDisplayInfoLocked([Landroid/view/SurfaceControl$PhysicalDisplayInfo;I[I[II)Z
-Lcom/android/server/display/DisplayDeviceInfo;->toString()Ljava/lang/String;
-Lcom/android/server/UiThread;->run()V
-Lcom/android/server/pm/PackageKeySetData;->setProperSigningKeySet(J)V
-Lcom/android/server/UiThread;->ensureThreadLocked()V
-Lcom/android/server/UiThread;->getHandler()Landroid/os/Handler;
-Lcom/android/server/pm/Settings;->getPackageLPr(Ljava/lang/String;)Lcom/android/server/pm/PackageSetting;
-Lcom/android/server/IoThread;->ensureThreadLocked()V
-Lcom/android/server/IoThread;->getHandler()Landroid/os/Handler;
-Lcom/android/server/pm/Settings;->getInternalVersion()Lcom/android/server/pm/Settings$VersionInfo;
-Lcom/android/server/appop/AppOpsService$Op;->running(JJII)V
-Lcom/android/server/appop/AppOpsService$Op;->updateAccessTimeAndDuration(JJII)V
-Lcom/android/server/appop/AppOpsService$Op;->rejected(JILjava/lang/String;II)V
-Lcom/android/server/DisplayThread;->ensureThreadLocked()V
-Lcom/android/server/DisplayThread;->getHandler()Landroid/os/Handler;
-Lcom/android/server/am/UserController;-><init>(Lcom/android/server/am/UserController$Injector;)V
-Lcom/android/server/AnimationThread;->ensureThreadLocked()V
-Lcom/android/server/AnimationThread;->getHandler()Landroid/os/Handler;
-Lcom/android/server/wm/SurfaceAnimationThread;->ensureThreadLocked()V
-Lcom/android/server/wm/SurfaceAnimationThread;->getHandler()Landroid/os/Handler;
-Lcom/android/server/wm/ActivityStackSupervisor;->initialize()V
-Lcom/android/server/pm/PackageSettingBase;->readUserState(I)Landroid/content/pm/PackageUserState;
-Lcom/android/server/pm/PackageManagerServiceUtils;->getCompressedFiles(Ljava/lang/String;)[Ljava/io/File;
-Lcom/android/server/pm/Settings;->insertPackageSettingLPw(Lcom/android/server/pm/PackageSetting;Landroid/content/pm/PackageParser$Package;)V
-Lcom/android/server/pm/ComponentResolver$ActivityIntentResolver;->addActivity(Landroid/content/pm/PackageParser$Activity;Ljava/lang/String;Ljava/util/List;)V
-Lcom/android/server/pm/Installer;->invalidateMounts()V
-Lcom/android/server/power/PowerManagerService$NativeWrapper;->nativeInit(Lcom/android/server/power/PowerManagerService;)V
-Lcom/android/server/power/ThermalManagerService;->onStart()V
-Lcom/android/server/am/OomAdjProfiler;-><init>()V
-Lcom/android/server/pm/PackageManagerService;->maybeClearProfilesForUpgradesLI(Lcom/android/server/pm/PackageSetting;Landroid/content/pm/PackageParser$Package;)V
-Lcom/android/server/am/ActivityManagerConstants;-><init>(Lcom/android/server/am/ActivityManagerService;Landroid/os/Handler;)V
-Lcom/android/server/IntentResolver;-><init>()V
-Lcom/android/server/pm/Settings;->updatePackageSetting(Lcom/android/server/pm/PackageSetting;Lcom/android/server/pm/PackageSetting;Lcom/android/server/pm/SharedUserSetting;Ljava/io/File;Ljava/io/File;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;IILjava/util/List;Lcom/android/server/pm/UserManagerService;[Ljava/lang/String;[J)V
-Lcom/android/server/PackageWatchdog;->loadFromFile()V
-Lcom/android/server/power/batterysaver/BatterySaverPolicy;-><init>(Ljava/lang/Object;Landroid/content/Context;Lcom/android/server/power/batterysaver/BatterySavingStats;)V
-Lcom/android/server/power/AttentionDetector;-><init>(Ljava/lang/Runnable;Ljava/lang/Object;)V
-Lcom/android/server/pm/dex/DexManager;-><init>(Landroid/content/Context;Landroid/content/pm/IPackageManager;Lcom/android/server/pm/PackageDexOptimizer;Lcom/android/server/pm/Installer;Ljava/lang/Object;)V
-Lcom/android/server/appop/AppOpsService$Op;-><init>(Lcom/android/server/appop/AppOpsService$UidState;Ljava/lang/String;I)V
-Lcom/android/server/pm/UserManagerService;->readUserLP(I)Lcom/android/server/pm/UserManagerService$UserData;
-Lcom/android/server/pm/UserManagerService;->readUserLP(ILjava/io/InputStream;)Lcom/android/server/pm/UserManagerService$UserData;
-Lcom/android/server/pm/UserRestrictionsUtils;->readRestrictions(Lorg/xmlpull/v1/XmlPullParser;)Landroid/os/Bundle;
-Lcom/android/server/pm/UserRestrictionsUtils;->readRestrictions(Lorg/xmlpull/v1/XmlPullParser;Landroid/os/Bundle;)V
-Lcom/android/server/pm/PackageManagerService;->adjustScanFlags(ILcom/android/server/pm/PackageSetting;Lcom/android/server/pm/PackageSetting;Landroid/os/UserHandle;Landroid/content/pm/PackageParser$Package;)I
+Lcom/android/server/appop/AppOpsService;->readUid(Lorg/xmlpull/v1/XmlPullParser;Ljava/lang/String;)V
+Lcom/android/server/appop/AppOpsService$Op;->updateProxyState(JILjava/lang/String;)V
+Lcom/android/server/appop/AppOpsService$Op;->accessed(JILjava/lang/String;II)V
+Lcom/android/server/pm/permission/PermissionSettings;->readPermissions(Landroid/util/ArrayMap;Lorg/xmlpull/v1/XmlPullParser;)V
+Lcom/android/server/pm/permission/BasePermission;-><init>(Ljava/lang/String;Ljava/lang/String;I)V
+Lcom/android/server/pm/permission/BasePermission;->readInt(Lorg/xmlpull/v1/XmlPullParser;Ljava/lang/String;Ljava/lang/String;I)I
+Lcom/android/server/pm/permission/BasePermission;->readLPw(Ljava/util/Map;Lorg/xmlpull/v1/XmlPullParser;)Z
+Lcom/android/server/pm/permission/PermissionsState$PermissionData;->isInstallPermission()Z
+Lcom/android/server/pm/permission/BasePermission;->getName()Ljava/lang/String;
+Lcom/android/server/pm/permission/PermissionsState$PermissionState;->access$100(Lcom/android/server/pm/permission/PermissionsState$PermissionState;)I
+Lcom/android/server/pm/permission/PermissionsState;->enforceValidUserId(I)V
+Lcom/android/server/pm/permission/PermissionsState;->hasPermission(Ljava/lang/String;I)Z
+Lcom/android/server/pm/permission/PermissionsState$PermissionData;->isGranted(I)Z
+Lcom/android/server/pm/permission/BasePermission;->computeGids(I)[I
+Lcom/android/server/pm/permission/PermissionsState;->appendInts([I[I)[I
+Lcom/android/server/pm/permission/PermissionsState;->computeGids(I)[I
+Lcom/android/server/pm/permission/PermissionsState$PermissionState;->access$000(Lcom/android/server/pm/permission/PermissionsState$PermissionState;)Z
+Lcom/android/server/pm/permission/PermissionsState$PermissionData;->computeGids(I)[I
+Lcom/android/server/pm/Settings;->readInstallPermissionsLPr(Lorg/xmlpull/v1/XmlPullParser;Lcom/android/server/pm/permission/PermissionsState;)V
+Lcom/android/server/pm/permission/PermissionsState$PermissionData;->isCompatibleUserId(I)Z
+Lcom/android/server/pm/permission/PermissionsState$PermissionData;->isDefault()Z
+Lcom/android/server/pm/permission/PermissionSettings;->getPermissionLocked(Ljava/lang/String;)Lcom/android/server/pm/permission/BasePermission;
+Lcom/android/server/pm/permission/PermissionSettings;->getPermission(Ljava/lang/String;)Lcom/android/server/pm/permission/BasePermission;
+Lcom/android/server/pm/permission/PermissionsState;->grantInstallPermission(Lcom/android/server/pm/permission/BasePermission;)I
+Lcom/android/server/pm/permission/PermissionsState;->grantPermission(Lcom/android/server/pm/permission/BasePermission;I)I
+Lcom/android/server/pm/permission/PermissionsState;->ensurePermissionData(Lcom/android/server/pm/permission/BasePermission;)Lcom/android/server/pm/permission/PermissionsState$PermissionData;
+Lcom/android/server/pm/permission/PermissionsState$PermissionData;-><init>(Lcom/android/server/pm/permission/BasePermission;)V
+Lcom/android/server/pm/permission/PermissionsState$PermissionData;->grant(I)Z
+Lcom/android/server/pm/permission/PermissionsState$PermissionState;-><init>(Ljava/lang/String;)V
+Lcom/android/server/pm/permission/PermissionsState$PermissionState;->access$002(Lcom/android/server/pm/permission/PermissionsState$PermissionState;Z)Z
+Lcom/android/server/pm/permission/PermissionsState;->updatePermissionFlags(Lcom/android/server/pm/permission/BasePermission;III)Z
+Lcom/android/server/pm/permission/PermissionsState$PermissionData;->getFlags(I)I
+Lcom/android/server/pm/permission/PermissionsState$PermissionData;->updateFlags(III)Z
+Lcom/android/server/pm/permission/PermissionsState$PermissionData;->isInstallPermissionKey(I)Z
+Lcom/android/server/pm/permission/PermissionsState$PermissionState;->access$102(Lcom/android/server/pm/permission/PermissionsState$PermissionState;I)I
+Lcom/android/server/pm/permission/PermissionsState$PermissionState;->isDefault()Z
+Lcom/android/server/pm/Settings;->readPackageLPw(Lorg/xmlpull/v1/XmlPullParser;)V
+Lcom/android/server/pm/PackageSignatures;->readCertsListXml(Lorg/xmlpull/v1/XmlPullParser;Ljava/util/ArrayList;Ljava/util/ArrayList;IZLandroid/content/pm/PackageParser$SigningDetails$Builder;)I
+Lcom/android/server/pm/Settings;->registerExistingAppIdLPw(ILcom/android/server/pm/SettingBase;Ljava/lang/Object;)Z
+Lcom/android/server/pm/Settings;->readLPw(Ljava/util/List;)Z
+Lcom/android/server/pm/SettingBase;-><init>(II)V
Lcom/android/server/pm/SettingBase;->setFlags(I)V
-Lcom/android/server/display/LogicalDisplay;->updateLocked(Ljava/util/List;)V
-Lcom/android/server/Watchdog$HandlerChecker;->run()V
-Lcom/android/server/Watchdog;->run()V
-Lcom/android/server/display/DisplayAdapter$1;->run()V
-Lcom/android/server/display/DisplayManagerService$DisplayManagerHandler;->handleMessage(Landroid/os/Message;)V
-Lcom/android/server/pm/PackageManagerServiceCompilerMapping;->getAndCheckValidity(I)Ljava/lang/String;
-Lcom/android/server/pm/ParallelPackageParser;->take()Lcom/android/server/pm/ParallelPackageParser$ParseResult;
-Lcom/android/server/pm/KeySetManagerService;->assertScannedPackageValid(Landroid/content/pm/PackageParser$Package;)V
-Lcom/android/server/display/LocalDisplayAdapter$LocalDisplayDevice$1;->run()V
-Lcom/android/server/pm/PackageManagerServiceUtils;->verifySignatures(Lcom/android/server/pm/PackageSetting;Lcom/android/server/pm/PackageSetting;Landroid/content/pm/PackageParser$SigningDetails;ZZ)Z
-Lcom/android/server/pm/PackageManagerService;->getSharedLibLatestVersionSetting(Lcom/android/server/pm/PackageManagerService$ScanResult;)Lcom/android/server/pm/PackageSetting;
-Lcom/android/server/display/LocalDisplayAdapter$LocalDisplayDevice$1;->setDisplayBrightness(I)V
-Lcom/android/server/pm/PackageManagerService;->getLatestSharedLibraVersionLPr(Landroid/content/pm/PackageParser$Package;)Landroid/content/pm/SharedLibraryInfo;
-Lcom/android/server/pm/PackageManagerServiceCompilerMapping;->getSystemPropertyName(I)Ljava/lang/String;
-Lcom/android/server/lights/LightsService$LightImpl;->setLightLocked(IIIII)V
-Lcom/android/server/lights/LightsService$LightImpl;->setBrightness(I)V
-Lcom/android/server/lights/LightsService$LightImpl;->setBrightness(II)V
-Lcom/android/server/Watchdog$HandlerChecker;->scheduleCheckLocked()V
+Lcom/android/server/pm/SettingBase;->setPrivateFlags(I)V
+Lcom/android/server/pm/permission/PermissionsState;-><init>()V
+Lcom/android/server/pm/PackageSignatures;-><init>()V
+Lcom/android/server/pm/PackageSetting;-><init>(Ljava/lang/String;Ljava/lang/String;Ljava/io/File;Ljava/io/File;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;JIILjava/lang/String;Ljava/util/List;I[Ljava/lang/String;[J)V
+Lcom/android/server/pm/PackageSettingBase;-><init>(Ljava/lang/String;Ljava/lang/String;Ljava/io/File;Ljava/io/File;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;JIILjava/lang/String;Ljava/util/List;[Ljava/lang/String;[J)V
+Lcom/android/server/pm/PackageKeySetData;-><init>()V
+Lcom/android/server/pm/PackageSettingBase;->init(Ljava/io/File;Ljava/io/File;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;J)V
+Lcom/android/server/pm/KeySetManagerService;->readKeySetListLPw(Lorg/xmlpull/v1/XmlPullParser;)V
+Lcom/android/server/pm/PackageSettingBase;->modifyUserState(I)Landroid/content/pm/PackageUserState;
+Lcom/android/server/pm/Settings;->readComponentsLPr(Lorg/xmlpull/v1/XmlPullParser;)Landroid/util/ArraySet;
+Lcom/android/server/pm/Settings;->readPackageRestrictionsLPr(I)V
+Lcom/android/server/pm/Settings$RuntimePermissionPersistence;->parsePermissionsLPr(Lorg/xmlpull/v1/XmlPullParser;Lcom/android/server/pm/permission/PermissionsState;I)V
+Lcom/android/server/pm/SettingBase;->getPermissionsState()Lcom/android/server/pm/permission/PermissionsState;
+Lcom/android/server/pm/Settings;->writeKernelMappingLPr()V
+Lcom/android/server/pm/PackageSettingBase;->getNotInstalledUserIds()[I
+Lcom/android/server/pm/PackageManagerService;-><init>(Lcom/android/server/pm/PackageManagerService$Injector;ZZ)V
+Lcom/android/server/pm/AppsFilter;->addPackage(Landroid/content/pm/PackageParser$Package;Ljava/util/Map;)V
+Lcom/android/server/pm/AppsFilter;->canQuery(Landroid/content/pm/PackageParser$Package;Landroid/content/pm/PackageParser$Package;)Z
+Lcom/android/server/pm/SELinuxMMAC;->getSeInfo(Landroid/content/pm/PackageParser$Package;ZI)Ljava/lang/String;
+Lcom/android/server/pm/Policy;->getMatchedSeInfo(Landroid/content/pm/PackageParser$Package;)Ljava/lang/String;
+Lcom/android/server/pm/PackageSettingBase;->readUserState(I)Landroid/content/pm/PackageUserState;
Lcom/android/server/pm/permission/PermissionsState;->copyFrom(Lcom/android/server/pm/permission/PermissionsState;)V
-Lcom/android/server/pm/permission/PermissionManagerService$PermissionManagerServiceInternalImpl;->addAllPermissionGroups(Landroid/content/pm/PackageParser$Package;Z)V
-Lcom/android/server/RecoverySystemService;->onStart()V
-Lcom/android/server/display/DisplayManagerService;->onBootPhase(I)V
-Lcom/android/server/am/ProcessList;->updateOomLevels(IIZ)V
-Lcom/android/server/am/OomAdjProfiler;->batteryPowerChanged(Z)V
-Lcom/android/server/pm/UserManagerService;->hasManageUsersOrPermission(Ljava/lang/String;)Z
-Lcom/android/server/am/OomAdjProfiler;->scheduleSystemServerCpuTimeUpdate()V
-Lcom/android/server/pm/PackageManagerService$ReconcileRequest;-><init>(Ljava/util/Map;Ljava/util/Map;Ljava/util/Map;Ljava/util/Map;Ljava/util/Map;Lcom/android/server/pm/PackageManagerService$1;)V
-Lcom/android/server/pm/PackageManagerService$ReconcileRequest;-><init>(Ljava/util/Map;Ljava/util/Map;Ljava/util/Map;Ljava/util/Map;Ljava/util/Map;Ljava/util/Map;Ljava/util/Map;Ljava/util/Map;)V
-Lcom/android/server/wm/ConfigurationContainer;->onConfigurationChanged(Landroid/content/res/Configuration;)V
-Lcom/android/server/wm/RootActivityContainer;-><init>(Lcom/android/server/wm/ActivityTaskManagerService;)V
-Lcom/android/server/wm/ActivityTaskManagerService;->createRecentTasks()Lcom/android/server/wm/RecentTasks;
-Lcom/android/server/am/OomAdjuster;->updateOomAdjLocked()V
-Lcom/android/server/am/OomAdjuster;->updateOomAdjLocked(Lcom/android/server/am/ProcessRecord;Z)Z
-Lcom/android/server/am/ActivityManagerService;->updateOomAdjLocked()V
-Lcom/android/server/am/ActivityManagerService;->updateOomAdjLocked(Lcom/android/server/am/ProcessRecord;Z)Z
+Lcom/android/server/pm/permission/PermissionsState$PermissionData;-><init>(Lcom/android/server/pm/permission/PermissionsState$PermissionData;)V
+Lcom/android/server/pm/permission/PermissionsState$PermissionState;-><init>(Lcom/android/server/pm/permission/PermissionsState$PermissionState;)V
+Lcom/android/server/pm/permission/BasePermission;->findPermissionTree(Ljava/util/Collection;Ljava/lang/String;)Lcom/android/server/pm/permission/BasePermission;
+Lcom/android/server/pm/permission/PermissionManagerService;->addAllPermissions(Landroid/content/pm/PackageParser$Package;Z)V
+Lcom/android/server/pm/permission/PermissionSettings;->putPermissionLocked(Ljava/lang/String;Lcom/android/server/pm/permission/BasePermission;)V
+Lcom/android/server/pm/permission/PermissionSettings;->getAllPermissionTreesLocked()Ljava/util/Collection;
+Lcom/android/server/pm/permission/BasePermission;->createOrUpdate(Lcom/android/server/pm/permission/BasePermission;Landroid/content/pm/PackageParser$Permission;Landroid/content/pm/PackageParser$Package;Ljava/util/Collection;Z)Lcom/android/server/pm/permission/BasePermission;
+Lcom/android/server/pm/PackageManagerService;->commitPackageSettings(Landroid/content/pm/PackageParser$Package;Landroid/content/pm/PackageParser$Package;Lcom/android/server/pm/PackageSetting;IZLcom/android/server/pm/PackageManagerService$ReconciledPackage;)V
+Lcom/android/server/IntentResolver;->register_intent_filter(Landroid/content/IntentFilter;Ljava/util/Iterator;Landroid/util/ArrayMap;Ljava/lang/String;)I
+Lcom/android/server/pm/PackageManagerService;->fixProcessName(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
+Lcom/android/server/pm/PackageManagerService;->isPackageRenamed(Landroid/content/pm/PackageParser$Package;Ljava/lang/String;)Z
+Lcom/android/server/pm/PackageSettingBase;->doCopy(Lcom/android/server/pm/PackageSettingBase;)V
+Lcom/android/server/pm/PackageSettingBase;->setTimeStamp(J)V
+Lcom/android/server/pm/PackageManagerService;->scanDirLI(Ljava/io/File;IIJ)V
+Lcom/android/server/pm/PackageManagerService$PackageParserCallback;->getStaticOverlayPackages(Ljava/util/Collection;Ljava/lang/String;)Ljava/util/List;
+Lcom/android/server/pm/ComponentResolver$ActivityIntentResolver;->addActivity(Landroid/content/pm/PackageParser$Activity;Ljava/lang/String;Ljava/util/List;)V
+Lcom/android/server/IntentResolver;->addFilter(Landroid/util/ArrayMap;Ljava/lang/String;Landroid/content/IntentFilter;)V
+Lcom/android/server/pm/PackageManagerService;->applyPolicy(Landroid/content/pm/PackageParser$Package;IILandroid/content/pm/PackageParser$Package;)V
+Lcom/android/server/pm/ComponentResolver;->addActivitiesLocked(Landroid/content/pm/PackageParser$Package;Ljava/util/List;Z)V
+Lcom/android/server/pm/ComponentResolver$ActivityIntentResolver;->access$600(Lcom/android/server/pm/ComponentResolver$ActivityIntentResolver;Landroid/content/pm/PackageParser$Activity;Ljava/lang/String;Ljava/util/List;)V
+Lcom/android/server/pm/Settings;->getDisabledSystemPkgLPr(Ljava/lang/String;)Lcom/android/server/pm/PackageSetting;
+Lcom/android/server/IntentResolver;->register_mime_types(Landroid/content/IntentFilter;Ljava/lang/String;)I
+Lcom/android/server/pm/Settings;->getPackageLPr(Ljava/lang/String;)Lcom/android/server/pm/PackageSetting;
+Lcom/android/server/pm/SettingBase;->doCopy(Lcom/android/server/pm/SettingBase;)V
+Lcom/android/server/pm/PackageManagerService;->reconcilePackagesLocked(Lcom/android/server/pm/PackageManagerService$ReconcileRequest;Lcom/android/server/pm/KeySetManagerService;)Ljava/util/Map;
+Lcom/android/server/pm/ComponentResolver$ActivityIntentResolver;->newArray(I)[Landroid/content/IntentFilter;
+Lcom/android/server/pm/ComponentResolver$ActivityIntentResolver;->newArray(I)[Landroid/content/pm/PackageParser$ActivityIntentInfo;
+Lcom/android/server/IntentResolver;->addFilter(Landroid/content/IntentFilter;)V
+Lcom/android/server/pm/Settings;->getSettingLPr(I)Lcom/android/server/pm/SettingBase;
+Lcom/android/server/pm/ComponentResolver;->addAllComponents(Landroid/content/pm/PackageParser$Package;Z)V
+Lcom/android/server/pm/ComponentResolver;->addServicesLocked(Landroid/content/pm/PackageParser$Package;Z)V
+Lcom/android/server/pm/UserManagerService;->getUsers(Z)Ljava/util/List;
+Lcom/android/server/pm/Settings;->getInternalVersion()Lcom/android/server/pm/Settings$VersionInfo;
Lcom/android/server/pm/Settings;->getRenamedPackageLPr(Ljava/lang/String;)Ljava/lang/String;
-Lcom/android/server/am/OomAdjProfiler;->updateSystemServerCpuTime(ZZ)V
+Lcom/android/server/pm/PackageManagerService;->getRealPackageName(Landroid/content/pm/PackageParser$Package;Ljava/lang/String;)Ljava/lang/String;
+Lcom/android/server/pm/PackageManagerService;->getOriginalPackageLocked(Landroid/content/pm/PackageParser$Package;Ljava/lang/String;)Lcom/android/server/pm/PackageSetting;
+Lcom/android/server/pm/PackageSetting;-><init>(Lcom/android/server/pm/PackageSetting;)V
+Lcom/android/server/pm/PackageSettingBase;-><init>(Lcom/android/server/pm/PackageSettingBase;Ljava/lang/String;)V
+Lcom/android/server/pm/SettingBase;-><init>(Lcom/android/server/pm/SettingBase;)V
+Lcom/android/server/pm/PackageSetting;->doCopy(Lcom/android/server/pm/PackageSetting;)V
+Lcom/android/server/pm/PackageManagerService;->isSystemApp(Landroid/content/pm/PackageParser$Package;)Z
+Lcom/android/server/pm/PackageManagerServiceUtils;->getLastModifiedTime(Landroid/content/pm/PackageParser$Package;)J
+Lcom/android/server/pm/PackageManagerService;->getSettingsVersionForPackage(Landroid/content/pm/PackageParser$Package;)Lcom/android/server/pm/Settings$VersionInfo;
+Lcom/android/server/pm/PackageManagerService;->isExternal(Landroid/content/pm/PackageParser$Package;)Z
+Lcom/android/server/pm/PackageManagerService;->isCompatSignatureUpdateNeeded(Lcom/android/server/pm/Settings$VersionInfo;)Z
+Lcom/android/server/pm/PackageManagerService;->isRecoverSignatureUpdateNeeded(Lcom/android/server/pm/Settings$VersionInfo;)Z
+Lcom/android/server/pm/PackageSettingBase;->updateFrom(Lcom/android/server/pm/PackageSettingBase;)Lcom/android/server/pm/PackageSettingBase;
Lcom/android/server/pm/UserManagerService;->getInstance()Lcom/android/server/pm/UserManagerService;
-Lcom/android/server/pm/permission/PermissionManagerService$PermissionManagerServiceInternalImpl;->addAllPermissions(Landroid/content/pm/PackageParser$Package;Z)V
-Lcom/android/server/power/PowerManagerService$Injector;->createBatterySaverPolicy(Ljava/lang/Object;Landroid/content/Context;Lcom/android/server/power/batterysaver/BatterySavingStats;)Lcom/android/server/power/batterysaver/BatterySaverPolicy;
-Lcom/android/server/power/ThermalManagerService;-><init>(Landroid/content/Context;)V
-Lcom/android/server/power/ThermalManagerService;-><init>(Landroid/content/Context;Lcom/android/server/power/ThermalManagerService$ThermalHalWrapper;)V
-Lcom/android/server/display/PersistentDataStore$Injector;->openRead()Ljava/io/InputStream;
-Lcom/android/server/pm/PackageManagerService$ReconciledPackage;-><init>(Lcom/android/server/pm/PackageManagerService$InstallArgs;Lcom/android/server/pm/PackageSetting;Lcom/android/server/pm/PackageManagerService$PackageInstalledInfo;Lcom/android/server/pm/PackageManagerService$PrepareResult;Lcom/android/server/pm/PackageManagerService$ScanResult;Lcom/android/server/pm/PackageManagerService$DeletePackageAction;Ljava/util/List;Landroid/content/pm/PackageParser$SigningDetails;ZZLcom/android/server/pm/PackageManagerService$1;)V
-Lcom/android/server/pm/ComponentResolver;-><init>(Lcom/android/server/pm/UserManagerService;Landroid/content/pm/PackageManagerInternal;Ljava/lang/Object;)V
-Lcom/android/server/wm/LaunchParamsController;->registerDefaultModifiers(Lcom/android/server/wm/ActivityStackSupervisor;)V
-Lcom/android/server/Watchdog$OpenFdMonitor;->create()Lcom/android/server/Watchdog$OpenFdMonitor;
+Lcom/android/server/pm/Settings;->writeUserRestrictionsLPw(Lcom/android/server/pm/PackageSetting;Lcom/android/server/pm/PackageSetting;)V
+Lcom/android/server/pm/KeySetManagerService;->getPublicKeysFromKeySetLPr(J)Landroid/util/ArraySet;
+Lcom/android/server/pm/PackageSettingBase;->getInstantApp(I)Z
+Lcom/android/server/pm/ComponentResolver;->addReceiversLocked(Landroid/content/pm/PackageParser$Package;Z)V
+Lcom/android/server/pm/ComponentResolver;->addProvidersLocked(Landroid/content/pm/PackageParser$Package;Z)V
+Lcom/android/server/pm/ComponentResolver$ServiceIntentResolver;->addService(Landroid/content/pm/PackageParser$Service;)V
+Lcom/android/server/pm/PackageManagerService$PackageManagerInternalImpl;->getDisabledSystemPackage(Ljava/lang/String;)Landroid/content/pm/PackageParser$Package;
+Lcom/android/server/pm/ComponentResolver;->adjustPriority(Ljava/util/List;Landroid/content/pm/PackageParser$ActivityIntentInfo;Ljava/lang/String;)V
+Lcom/android/server/pm/ComponentResolver;->isProtectedAction(Landroid/content/pm/PackageParser$ActivityIntentInfo;)Z
+Lcom/android/server/pm/Settings;->addPackageSettingLPw(Lcom/android/server/pm/PackageSetting;Lcom/android/server/pm/SharedUserSetting;)V
+Lcom/android/server/pm/PackageInstallerService;->isStageName(Ljava/lang/String;)Z
+Lcom/android/server/pm/ParallelPackageParser;->submit(Ljava/io/File;I)V
+Lcom/android/server/pm/-$$Lambda$ParallelPackageParser$FTtinPrp068lVeI7K6bC1tNE3iM;-><init>(Lcom/android/server/pm/ParallelPackageParser;Ljava/io/File;I)V
+Lcom/android/server/IntentResolver;->filterEquals(Landroid/content/IntentFilter;Landroid/content/IntentFilter;)Z
+Lcom/android/server/IntentResolver;->collectFilters([Landroid/content/IntentFilter;Landroid/content/IntentFilter;)Ljava/util/ArrayList;
+Lcom/android/server/pm/-$$Lambda$ParallelPackageParser$FTtinPrp068lVeI7K6bC1tNE3iM;->run()V
+Lcom/android/server/pm/ParallelPackageParser;->lambda$submit$0$ParallelPackageParser(Ljava/io/File;I)V
+Lcom/android/server/pm/ParallelPackageParser$ParseResult;-><init>()V
+Lcom/android/server/pm/ParallelPackageParser;->parsePackage(Landroid/content/pm/PackageParser;Ljava/io/File;I)Landroid/content/pm/PackageParser$Package;
+Lcom/android/server/pm/PackageManagerService$PackageParserCallback;->getOverlayApks(Ljava/lang/String;)[Ljava/lang/String;
+Lcom/android/server/pm/PackageManagerService$ParallelPackageParserCallback;->getStaticOverlayPaths(Ljava/lang/String;Ljava/lang/String;)[Ljava/lang/String;
+Lcom/android/server/IntentResolver;->findFilters(Landroid/content/IntentFilter;)Ljava/util/ArrayList;
+Lcom/android/server/pm/ComponentResolver;->findMatchingActivity(Ljava/util/List;Landroid/content/pm/ActivityInfo;)Landroid/content/pm/PackageParser$Activity;
+Lcom/android/server/pm/ComponentResolver$ProviderIntentResolver;->addProvider(Landroid/content/pm/PackageParser$Provider;)V
+Lcom/android/server/pm/PackageManagerService$Injector$Singleton;->get(Lcom/android/server/pm/PackageManagerService$Injector;Lcom/android/server/pm/PackageManagerService;)Ljava/lang/Object;
+Lcom/android/server/pm/ParallelPackageParser;->take()Lcom/android/server/pm/ParallelPackageParser$ParseResult;
+Lcom/android/server/pm/PackageManagerService;->scanPackageOnlyLI(Lcom/android/server/pm/PackageManagerService$ScanRequest;Lcom/android/server/pm/PackageManagerService$Injector;ZJ)Lcom/android/server/pm/PackageManagerService$ScanResult;
+Lcom/android/server/pm/PackageManagerService$Injector;->getUserManagerService()Lcom/android/server/pm/UserManagerService;
+Lcom/android/server/pm/ComponentResolver;->getIntentListSubset(Ljava/util/List;Lcom/android/server/pm/ComponentResolver$IterGenerator;Ljava/util/Iterator;)V
+Lcom/android/server/pm/PackageManagerService;->scanPackageChildLI(Landroid/content/pm/PackageParser$Package;IIJLandroid/os/UserHandle;)Landroid/content/pm/PackageParser$Package;
+Lcom/android/server/pm/PackageManagerService;->addForInitLI(Landroid/content/pm/PackageParser$Package;IIJLandroid/os/UserHandle;)Landroid/content/pm/PackageParser$Package;
+Lcom/android/server/pm/PackageManagerServiceUtils;->getCompressedFiles(Ljava/lang/String;)[Ljava/io/File;
+Lcom/android/server/pm/PackageManagerService$ScanRequest;-><init>(Landroid/content/pm/PackageParser$Package;Lcom/android/server/pm/SharedUserSetting;Landroid/content/pm/PackageParser$Package;Lcom/android/server/pm/PackageSetting;Lcom/android/server/pm/PackageSetting;Lcom/android/server/pm/PackageSetting;Ljava/lang/String;IIZLandroid/os/UserHandle;)V
+Lcom/android/server/pm/PackageManagerService$Injector;->getAbiHelper()Lcom/android/server/pm/PackageAbiHelper;
+Lcom/android/server/pm/PackageManagerService$Injector;->getUserManagerInternal()Landroid/os/UserManagerInternal;
+Lcom/android/server/pm/UserManagerService;->getInternalForInjectorOnly()Landroid/os/UserManagerInternal;
+Lcom/android/server/pm/Settings;->updatePackageSetting(Lcom/android/server/pm/PackageSetting;Lcom/android/server/pm/PackageSetting;Lcom/android/server/pm/SharedUserSetting;Ljava/io/File;Ljava/io/File;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;IILjava/util/List;Lcom/android/server/pm/UserManagerService;[Ljava/lang/String;[J)V
+Lcom/android/server/pm/PackageManagerService;->setInstantAppForUser(Lcom/android/server/pm/PackageManagerService$Injector;Lcom/android/server/pm/PackageSetting;IZZ)V
+Lcom/android/server/pm/PackageManagerServiceUtils;->deriveAbiOverride(Ljava/lang/String;Lcom/android/server/pm/PackageSetting;)Ljava/lang/String;
+Lcom/android/server/pm/PackageAbiHelperImpl;->getNativeLibraryPaths(Landroid/content/pm/PackageParser$Package;Ljava/io/File;)Lcom/android/server/pm/PackageAbiHelper$NativeLibraryPaths;
+Lcom/android/server/pm/PackageAbiHelper$Abis;-><init>(Landroid/content/pm/PackageParser$Package;)V
+Lcom/android/server/pm/PackageAbiHelper$Abis;-><init>(Ljava/lang/String;Ljava/lang/String;)V
+Lcom/android/server/pm/PackageAbiHelperImpl;->getNativeLibraryPaths(Lcom/android/server/pm/PackageAbiHelper$Abis;Ljava/io/File;Ljava/lang/String;Ljava/lang/String;ZZ)Lcom/android/server/pm/PackageAbiHelper$NativeLibraryPaths;
+Lcom/android/server/pm/InstructionSets;->getPrimaryInstructionSet(Lcom/android/server/pm/PackageAbiHelper$Abis;)Ljava/lang/String;
+Lcom/android/server/pm/PackageAbiHelper$NativeLibraryPaths;-><init>(Ljava/lang/String;ZLjava/lang/String;Ljava/lang/String;)V
+Lcom/android/server/pm/PackageAbiHelper$NativeLibraryPaths;->applyTo(Landroid/content/pm/PackageParser$Package;)V
+Lcom/android/server/pm/PackageManagerService$ScanResult;-><init>(Lcom/android/server/pm/PackageManagerService$ScanRequest;ZLcom/android/server/pm/PackageSetting;Ljava/util/List;ZLandroid/content/pm/SharedLibraryInfo;Ljava/util/List;)V
+Lcom/android/server/pm/PackageSetting;->updateFrom(Lcom/android/server/pm/PackageSetting;)V
+Lcom/android/server/pm/SettingBase;->copyFrom(Lcom/android/server/pm/SettingBase;)V
+Lcom/android/server/pm/ComponentResolver$ActivityIntentResolver;->allowFilterResult(Landroid/content/pm/PackageParser$ActivityIntentInfo;Ljava/util/List;)Z
+Lcom/android/server/pm/PackageManagerService;->executeSharedLibrariesUpdateLPr(Landroid/content/pm/PackageParser$Package;Landroid/content/pm/PackageParser$Package;Ljava/util/ArrayList;)V
+Lcom/android/server/pm/PackageManagerService;->collectSharedLibraryInfos(Ljava/util/List;[J[[Ljava/lang/String;Ljava/lang/String;ZILjava/util/ArrayList;Ljava/util/Map;Ljava/util/Map;Ljava/util/Map;)Ljava/util/ArrayList;
+Lcom/android/server/pm/PackageManagerService;->getSharedLibraryInfo(Ljava/lang/String;JLjava/util/Map;Ljava/util/Map;)Landroid/content/pm/SharedLibraryInfo;
+Lcom/android/server/pm/PackageManagerService;->addSharedLibraryLPr(Landroid/content/pm/PackageParser$Package;Ljava/util/Set;Landroid/content/pm/SharedLibraryInfo;Landroid/content/pm/PackageParser$Package;)V
+Lcom/android/server/pm/PackageUsage;->readToken(Ljava/io/InputStream;Ljava/lang/StringBuffer;C)Ljava/lang/String;
+Lcom/android/server/pm/PackageUsage;->readVersion1LP(Ljava/util/Map;Ljava/io/InputStream;Ljava/lang/StringBuffer;)V
+Lcom/android/server/pm/PackageUsage;->parseAsLong(Ljava/lang/String;)J
+Lcom/android/server/pm/CompilerStats;->read(Ljava/io/Reader;)Z
+Lcom/android/server/pm/permission/BasePermission;->getSourcePackageSetting()Lcom/android/server/pm/PackageSettingBase;
+Lcom/android/server/pm/permission/PermissionManagerService;->updatePermissionSourcePackage(Ljava/lang/String;Landroid/content/pm/PackageParser$Package;)Z
+Lcom/android/server/pm/permission/BasePermission;->isDynamic()Z
+Lcom/android/server/pm/permission/PermissionManagerService;->cacheBackgroundToForegoundPermissionMapping()V
+Lcom/android/server/pm/PackageManagerService$PackageManagerInternalImpl;->getKnownPackageName(II)Ljava/lang/String;
+Lcom/android/server/pm/PackageSetting;->isSystem()Z
+Lcom/android/server/pm/permission/PermissionsState;->hasInstallPermission(Ljava/lang/String;)Z
+Lcom/android/server/pm/permission/PermissionsState;->getPermissions(I)Ljava/util/Set;
+Lcom/android/server/pm/permission/PermissionManagerService;->revokePermissionsNoLongerImplicitLocked(Lcom/android/server/pm/permission/PermissionsState;Landroid/content/pm/PackageParser$Package;[I)[I
+Lcom/android/server/pm/PackageSetting;->getPermissionsState()Lcom/android/server/pm/permission/PermissionsState;
+Lcom/android/server/pm/permission/PermissionsState;->grantRuntimePermission(Lcom/android/server/pm/permission/BasePermission;I)I
+Lcom/android/server/pm/permission/PermissionManagerService;->restorePermissionState(Landroid/content/pm/PackageParser$Package;ZLjava/lang/String;Lcom/android/server/pm/permission/PermissionManagerServiceInternal$PermissionCallback;)V
+Lcom/android/server/pm/permission/PermissionsState;->getPermissionState(Ljava/lang/String;I)Lcom/android/server/pm/permission/PermissionsState$PermissionState;
+Lcom/android/server/pm/permission/PermissionsState$PermissionData;->getPermissionState(I)Lcom/android/server/pm/permission/PermissionsState$PermissionState;
+Lcom/android/server/pm/PackageSettingBase;->getPermissionsState()Lcom/android/server/pm/permission/PermissionsState;
+Lcom/android/server/pm/permission/PermissionsState;->getRuntimePermissionState(Ljava/lang/String;I)Lcom/android/server/pm/permission/PermissionsState$PermissionState;
+Lcom/android/server/pm/permission/PermissionsState;->hasRequestedPermission(Ljava/lang/String;)Z
+Lcom/android/server/pm/permission/BasePermission;->isRuntimeOnly()Z
+Lcom/android/server/pm/permission/BasePermission;->isAppOp()Z
+Lcom/android/server/pm/permission/BasePermission;->isNormal()Z
+Lcom/android/server/pm/permission/PermissionManagerService;->setInitialGrantForNewImplicitPermissionsLocked(Lcom/android/server/pm/permission/PermissionsState;Lcom/android/server/pm/permission/PermissionsState;Landroid/content/pm/PackageParser$Package;Landroid/util/ArraySet;[I)[I
+Lcom/android/server/pm/UserManagerService;->getUserIds()[I
+Lcom/android/server/pm/permission/PermissionsState$PermissionState;->getFlags()I
+Lcom/android/server/pm/permission/BasePermission;->isRuntime()Z
+Lcom/android/server/pm/permission/PermissionsState;->hasRuntimePermission(Ljava/lang/String;I)Z
+Lcom/android/server/pm/PackageSettingBase;->getSigningDetails()Landroid/content/pm/PackageParser$SigningDetails;
+Lcom/android/server/pm/permission/BasePermission;->isVendorPrivileged()Z
+Lcom/android/server/pm/permission/BasePermission;->isSignature()Z
+Lcom/android/server/pm/permission/PermissionManagerService;->grantSignaturePermission(Ljava/lang/String;Landroid/content/pm/PackageParser$Package;Lcom/android/server/pm/permission/BasePermission;Lcom/android/server/pm/permission/PermissionsState;)Z
+Lcom/android/server/pm/permission/BasePermission;->isOEM()Z
+Lcom/android/server/pm/permission/BasePermission;->isPrivileged()Z
+Lcom/android/server/pm/permission/BasePermission;->getSourcePackageName()Ljava/lang/String;
+Lcom/android/server/pm/PackageManagerService$PackageManagerInternalImpl;->getPackage(Ljava/lang/String;)Landroid/content/pm/PackageParser$Package;
+Lcom/android/server/pm/PackageManagerService;->access$5700(Lcom/android/server/pm/PackageManagerService;Ljava/lang/String;J)Ljava/lang/String;
+Lcom/android/server/pm/PackageManagerService;->resolveInternalPackageNameLPr(Ljava/lang/String;J)Ljava/lang/String;
+Lcom/android/server/pm/permission/PermissionsState;->getPermissionFlags(Ljava/lang/String;I)I
+Lcom/android/server/pm/permission/PermissionsState;->getInstallPermissionState(Ljava/lang/String;)Lcom/android/server/pm/permission/PermissionsState$PermissionState;
+Lcom/android/server/pm/permission/PermissionManagerService;->hasPrivappWhitelistEntry(Ljava/lang/String;Landroid/content/pm/PackageParser$Package;)Z
+Lcom/android/server/pm/permission/BasePermission;->isHardRestricted()Z
+Lcom/android/server/pm/permission/BasePermission;->isSoftRestricted()Z
+Lcom/android/server/pm/permission/PermissionsState$PermissionState;->isGranted()Z
+Lcom/android/server/pm/PackageManagerService;->reconcileAppsDataLI(Ljava/lang/String;IIZZ)Ljava/util/List;
+Lcom/android/server/pm/permission/BasePermission;->writeLPr(Lorg/xmlpull/v1/XmlSerializer;)V
+Lcom/android/server/pm/permission/PermissionSettings;->writePermissions(Lorg/xmlpull/v1/XmlSerializer;)V
+Lcom/android/server/pm/permission/PermissionsState;->getPermissionStatesInternal(I)Ljava/util/List;
+Lcom/android/server/pm/Settings;->writePermissionsLPr(Lorg/xmlpull/v1/XmlSerializer;Ljava/util/List;)V
+Lcom/android/server/pm/permission/PermissionsState$PermissionState;->getName()Ljava/lang/String;
+Lcom/android/server/pm/PackageKeySetData;->getProperSigningKeySet()J
+Lcom/android/server/pm/PackageSignatures;->writeCertsListXml(Lorg/xmlpull/v1/XmlSerializer;Ljava/util/ArrayList;[Landroid/content/pm/Signature;Z)V
+Lcom/android/server/pm/Settings;->writeLPr()V
+Lcom/android/server/pm/Settings;->writeUsesStaticLibLPw(Lorg/xmlpull/v1/XmlSerializer;[Ljava/lang/String;[J)V
+Lcom/android/server/pm/Settings;->writeChildPackagesLPw(Lorg/xmlpull/v1/XmlSerializer;Ljava/util/List;)V
+Lcom/android/server/pm/permission/PermissionsState;->getInstallPermissionStates()Ljava/util/List;
+Lcom/android/server/pm/KeySetManagerService$PublicKeyHandle;->getKey()Ljava/security/PublicKey;
+Lcom/android/server/pm/Settings;->writeKernelMappingLPr(Ljava/lang/String;I[I)V
+Lcom/android/server/pm/Settings;->writeIntToFile(Ljava/io/File;I)V
+Lcom/android/server/pm/Settings;->writeKernelMappingLPr(Lcom/android/server/pm/PackageSetting;)V
+Lcom/android/server/pm/Settings;->writePackageListLPrInternal(I)V
+Lcom/android/server/pm/permission/PermissionsState;->computeGids([I)[I
+Lcom/android/server/pm/Settings;->writePackageRestrictionsLPr(I)V
+Lcom/android/server/IntentResolver;->buildResolveList(Landroid/content/Intent;Landroid/util/FastImmutableArraySet;ZZLjava/lang/String;Ljava/lang/String;[Landroid/content/IntentFilter;Ljava/util/List;I)V
+Lcom/android/server/pm/ComponentResolver$ActivityIntentResolver;->allowFilterResult(Landroid/content/IntentFilter;Ljava/util/List;)Z
+Lcom/android/server/pm/ComponentResolver$ActivityIntentResolver;->queryIntentForPackage(Landroid/content/Intent;Ljava/lang/String;ILjava/util/List;I)Ljava/util/List;
+Lcom/android/server/pm/ComponentResolver$ActivityIntentResolver;->isPackageForFilter(Ljava/lang/String;Landroid/content/IntentFilter;)Z
+Lcom/android/server/pm/ComponentResolver$ActivityIntentResolver;->isPackageForFilter(Ljava/lang/String;Landroid/content/pm/PackageParser$ActivityIntentInfo;)Z
+Lcom/android/server/pm/PackageSettingBase;->getInstalled(I)Z
+Lcom/android/server/pm/PackageManagerService;->getInstantAppPackageName(I)Ljava/lang/String;
+Lcom/android/server/pm/PackageManagerService;->shouldFilterApplicationLocked(Lcom/android/server/pm/PackageSetting;II)Z
+Lcom/android/server/pm/PackageManagerService;->shouldFilterApplicationLocked(Lcom/android/server/pm/PackageSetting;ILandroid/content/ComponentName;II)Z
+Lcom/android/server/pm/PackageManagerService;->isCallerSameApp(Ljava/lang/String;I)Z
+Lcom/android/server/pm/AppsFilter;->shouldFilterApplication(ILcom/android/server/pm/SettingBase;Lcom/android/server/pm/PackageSetting;I)Z
+Lcom/android/server/pm/UserManagerService$LocalService;->exists(I)Z
+Lcom/android/server/pm/UserManagerService;->access$2900(Lcom/android/server/pm/UserManagerService;I)Landroid/content/pm/UserInfo;
+Lcom/android/server/pm/UserManagerService;->getUserInfoNoChecks(I)Landroid/content/pm/UserInfo;
+Lcom/android/server/pm/UserManagerService;->exists(I)Z
+Lcom/android/server/pm/dex/DexManager;->putIfAbsent(Ljava/util/Map;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
+Lcom/android/server/pm/dex/DexManager;->cachePackageCodeLocation(Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;[Ljava/lang/String;I)V
+Lcom/android/server/pm/dex/DexManager$PackageCodeLocations;->mergeAppDataDirs(Ljava/lang/String;I)V
+Lcom/android/server/pm/dex/DexManager;->access$300(Ljava/util/Map;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
+Lcom/android/server/pm/dex/DexManager$PackageCodeLocations;->updateCodeLocation(Ljava/lang/String;[Ljava/lang/String;)V
+Lcom/android/server/appop/AppOpsService$Op;->access$100(Lcom/android/server/appop/AppOpsService$Op;)I
+Lcom/android/server/pm/PackageManagerService;->generatePackageInfo(Lcom/android/server/pm/PackageSetting;II)Landroid/content/pm/PackageInfo;
+Lcom/android/server/pm/PackageManagerService;->resolveExternalPackageNameLPr(Landroid/content/pm/PackageParser$Package;)Ljava/lang/String;
+Lcom/android/server/pm/Settings$RuntimePermissionPersistence;->writePermissionsSync(I)V
+Lcom/android/server/pm/Settings$RuntimePermissionPersistence;->writePermissions(Lorg/xmlpull/v1/XmlSerializer;Ljava/util/List;)V
+Lcom/android/server/om/OverlayManagerSettings$SettingsItem;->access$1600(Lcom/android/server/om/OverlayManagerSettings$SettingsItem;)I
+Lcom/android/server/pm/PackageManagerService;->filterSharedLibPackageLPr(Lcom/android/server/pm/PackageSetting;III)Z
+Lcom/android/server/om/OverlayManagerSettings;->select(Ljava/lang/String;I)I
+Lcom/android/server/om/OverlayManagerSettings$SettingsItem;->access$1100(Lcom/android/server/om/OverlayManagerSettings$SettingsItem;)Ljava/lang/String;
+Lcom/android/server/pm/PackageManagerServiceUtils;->compareSignatures([Landroid/content/pm/Signature;[Landroid/content/pm/Signature;)I
+Lcom/android/server/om/-$$Lambda$OverlayManagerSettings$Fjt465P6G89HQZERZFsOEjMbtXI;->test(Ljava/lang/Object;)Z
+Lcom/android/server/om/OverlayManagerSettings;->lambda$selectWhereUser$10(ILcom/android/server/om/OverlayManagerSettings$SettingsItem;)Z
+Lcom/android/server/om/OverlayManagerSettings$SettingsItem;->access$1000(Lcom/android/server/om/OverlayManagerSettings$SettingsItem;)Ljava/lang/String;
+Lcom/android/server/om/OverlayManagerSettings$SettingsItem;->getTargetPackageName()Ljava/lang/String;
+Lcom/android/server/om/-$$Lambda$OverlayManagerSettings$L_Sj43p2Txm_KH-wT0lseBTVzh8;->test(Ljava/lang/Object;)Z
+Lcom/android/server/om/OverlayManagerSettings;->lambda$selectWhereTarget$11(Ljava/lang/String;Lcom/android/server/om/OverlayManagerSettings$SettingsItem;)Z
+Lcom/android/server/om/OverlayManagerService;->updateOverlayPaths(ILjava/util/List;)V
+Lcom/android/server/usage/UsageStatsProto;->loadUsageStats(Landroid/util/proto/ProtoInputStream;JLcom/android/server/usage/IntervalStats;Ljava/util/List;)V
+Lcom/android/server/usage/UsageStatsProto;->read(Ljava/io/InputStream;Lcom/android/server/usage/IntervalStats;)V
+Lcom/android/server/usage/UsageStatsProto;->readStringPool(Landroid/util/proto/ProtoInputStream;)Ljava/util/List;
+Lcom/android/server/usage/IntervalStats;->getOrCreateUsageStats(Ljava/lang/String;)Landroid/app/usage/UsageStats;
+Lcom/android/server/usage/IntervalStats;->getCachedStringRef(Ljava/lang/String;)Ljava/lang/String;
+Lcom/android/server/pm/ComponentResolver$ProviderIntentResolver;->access$400(Lcom/android/server/pm/ComponentResolver$ProviderIntentResolver;)Landroid/util/ArrayMap;
+Lcom/android/server/pm/ComponentResolver;->queryProviders(Ljava/lang/String;Ljava/lang/String;III)Ljava/util/List;
+Lcom/android/server/pm/PackageManagerService;->getInstalledPackages(II)Landroid/content/pm/ParceledListSlice;
+Lcom/android/server/content/ContentService$ObserverNode;->addObserverLocked(Landroid/net/Uri;ILandroid/database/IContentObserver;ZLjava/lang/Object;III)V
+Lcom/android/server/am/ActivityManagerService;->registerReceiver(Landroid/app/IApplicationThread;Ljava/lang/String;Landroid/content/IIntentReceiver;Landroid/content/IntentFilter;Ljava/lang/String;II)Landroid/content/Intent;
+Lcom/android/server/appop/AppOpsService;->evalAllForegroundOpsLocked()V
+Lcom/android/server/DropBoxManagerService$EntryFile;->compareTo(Ljava/lang/Object;)I
+Lcom/android/server/DropBoxManagerService$EntryFile;->compareTo(Lcom/android/server/DropBoxManagerService$EntryFile;)I
+Lcom/android/server/DropBoxManagerService$EntryFile;->hasFile()Z
+Lcom/android/server/DropBoxManagerService;->init()V
+Lcom/android/server/DropBoxManagerService$EntryFile;-><init>(Ljava/io/File;I)V
+Lcom/android/server/DropBoxManagerService;->enrollEntry(Lcom/android/server/DropBoxManagerService$EntryFile;)V
+Lcom/android/server/ThreadPriorityBooster;->boost()V
+Lcom/android/server/ThreadPriorityBooster;->reset()V
+Lcom/android/server/wm/DisplayPolicy;->hasNavigationBar()Z
+Lcom/android/server/wm/DisplayPolicy;->navigationBarPosition(III)I
+Lcom/android/server/wm/DisplayPolicy;->navigationBarCanMove()Z
+Lcom/android/server/PersistentDataBlockService;->computeDigestLocked([B)[B
+Lcom/android/server/am/ActivityManagerService;->boostPriorityForLockedSection()V
+Lcom/android/server/am/ActivityManagerService;->resetPriorityAfterLockedSection()V
+Lcom/android/server/PinnerService;->clamp(III)I
+Lcom/android/server/am/ActivityManagerService;->checkComponentPermission(Ljava/lang/String;IIIZ)I
+Lcom/android/server/notification/PreferencesHelper;->readXml(Lorg/xmlpull/v1/XmlPullParser;ZI)V
+Lcom/android/server/pm/PackageManagerService;->updateFlags(II)I
+Lcom/android/server/pm/UserManagerService;->access$2800(Lcom/android/server/pm/UserManagerService;)Landroid/util/SparseIntArray;
+Lcom/android/server/pm/ComponentResolver$ServiceIntentResolver;->queryIntentForPackage(Landroid/content/Intent;Ljava/lang/String;ILjava/util/List;I)Ljava/util/List;
+Lcom/android/server/IntentResolver;->queryIntentFromList(Landroid/content/Intent;Ljava/lang/String;ZLjava/util/ArrayList;I)Ljava/util/List;
+Lcom/android/server/pm/ComponentResolver$ServiceIntentResolver;->allowFilterResult(Landroid/content/pm/PackageParser$ServiceIntentInfo;Ljava/util/List;)Z
+Lcom/android/server/pm/ComponentResolver$ServiceIntentResolver;->allowFilterResult(Landroid/content/IntentFilter;Ljava/util/List;)Z
+Lcom/android/server/pm/ComponentResolver$ServiceIntentResolver;->isPackageForFilter(Ljava/lang/String;Landroid/content/IntentFilter;)Z
+Lcom/android/server/pm/ComponentResolver$ServiceIntentResolver;->isPackageForFilter(Ljava/lang/String;Landroid/content/pm/PackageParser$ServiceIntentInfo;)Z
+Lcom/android/server/notification/PreferencesHelper;->writeXml(Lorg/xmlpull/v1/XmlSerializer;ZI)V
+Lcom/android/server/am/UserController;->handleIncomingUser(IIIZILjava/lang/String;Ljava/lang/String;)I
+Lcom/android/server/am/UserController;->unsafeConvertIncomingUser(I)I
+Lcom/android/server/audio/AudioService$VolumeStreamState;->hasValidSettingsName()Z
+Lcom/android/server/audio/AudioService$VolumeStreamState;->readSettings()V
+Lcom/android/server/am/ActivityManagerService;->handleIncomingUser(IIIZZLjava/lang/String;Ljava/lang/String;)I
+Lcom/android/server/am/UserController;->getCurrentUserId()I
+Lcom/android/server/am/UserController;->ensureNotSpecialUser(I)V
+Lcom/android/server/audio/AudioService;->access$2800(Lcom/android/server/audio/AudioService;)Landroid/content/ContentResolver;
+Lcom/android/server/audio/AudioService$VolumeStreamState;->getSettingNameForDevice(I)Ljava/lang/String;
+Lcom/android/server/pm/permission/PermissionManagerService$PermissionManagerServiceInternalImpl;->enforceCrossUserPermission(IIZZLjava/lang/String;)V
+Lcom/android/server/pm/permission/PermissionManagerService;->access$1900(Lcom/android/server/pm/permission/PermissionManagerService;IIZZZLjava/lang/String;)V
+Lcom/android/server/pm/permission/PermissionManagerService;->enforceCrossUserPermission(IIZZZLjava/lang/String;)V
+Lcom/android/server/pm/UserManagerService;->userWithName(Landroid/content/pm/UserInfo;)Landroid/content/pm/UserInfo;
+Lcom/android/server/pm/UserManagerService;->checkManageOrCreateUsersPermission(Ljava/lang/String;)V
+Lcom/android/server/pm/UserManagerService;->hasManageOrCreateUsersPermission()Z
+Lcom/android/server/pm/UserManagerService;->hasManageUsersOrPermission(Ljava/lang/String;)Z
+Lcom/android/server/utils/TimingsTraceAndSlog;->traceBegin(Ljava/lang/String;)V
+Lcom/android/server/utils/TimingsTraceAndSlog;->logDuration(Ljava/lang/String;J)V
+Lcom/android/server/pm/PackageManagerService;->addPackageHoldingPermissions(Ljava/util/ArrayList;Lcom/android/server/pm/PackageSetting;[Ljava/lang/String;[ZII)V
+Lcom/android/server/pm/PackageManagerService;->updateFlagsForPackage(IILjava/lang/Object;)I
+Lcom/android/server/am/ActivityManagerService;->checkPermission(Ljava/lang/String;II)I
+Lcom/android/server/pm/UserManagerService;->isUserUnlockingOrUnlocked(I)Z
+Lcom/android/server/pm/UserManagerService;->checkManageOrInteractPermIfCallerInOtherProfileGroup(ILjava/lang/String;)V
+Lcom/android/server/pm/UserManagerService$LocalService;->isUserUnlockingOrUnlocked(I)Z
+Lcom/android/server/pm/PackageManagerService;->updateFlagsForComponent(IILjava/lang/Object;)I
Lcom/android/server/SystemServiceManager;->warnIfTooLong(JLcom/android/server/SystemService;Ljava/lang/String;)V
-Lcom/android/server/am/UserController$Injector;->getLockPatternUtils()Lcom/android/internal/widget/LockPatternUtils;
-Lcom/android/server/am/PendingIntentController;-><init>(Landroid/os/Looper;Lcom/android/server/am/UserController;)V
-Lcom/android/server/am/BroadcastQueue;-><init>(Lcom/android/server/am/ActivityManagerService;Landroid/os/Handler;Ljava/lang/String;Lcom/android/server/am/BroadcastConstants;Z)V
-Lcom/android/server/display/LocalDisplayAdapter$LocalDisplayDevice$1;->setDisplayState(I)V
-Lcom/android/server/am/BatteryStatsService$WakeupReasonThread;->waitWakeup()Ljava/lang/String;
+Lcom/android/server/PinnerService;->pinFileRanges(Ljava/lang/String;ILcom/android/server/PinnerService$PinRangeSource;)Lcom/android/server/PinnerService$PinnedFile;
+Lcom/android/server/PinnerService$PinRangeSourceStream;->read(Lcom/android/server/PinnerService$PinRange;)Z
+Lcom/android/server/am/ReceiverList;->containsFilter(Landroid/content/IntentFilter;)Z
+Lcom/android/server/pm/Settings;->isEnabledAndMatchLPr(Landroid/content/pm/ComponentInfo;II)Z
+Lcom/android/server/pm/permission/PermissionManagerService;->access$2100(Lcom/android/server/pm/permission/PermissionManagerService;)Lcom/android/server/pm/permission/PermissionSettings;
+Lcom/android/server/pm/permission/PermissionManagerService$PermissionManagerServiceInternalImpl;->getAllPermissionWithProtectionLevel(I)Ljava/util/ArrayList;
+Lcom/android/server/pm/PackageManagerService;->forEachPackage(Ljava/util/function/Consumer;)V
+Lcom/android/server/pm/permission/PermissionManagerService;->access$200(Lcom/android/server/pm/permission/PermissionManagerService;)Landroid/content/pm/PackageManagerInternal;
+Lcom/android/server/pm/permission/-$$Lambda$PermissionManagerService$7fYYDxKgBF9e9QlxmWAdwL0CsDs;->accept(Ljava/lang/Object;)V
+Lcom/android/server/pm/permission/PermissionManagerService;->lambda$updatePermissions$10$PermissionManagerService(Landroid/content/pm/PackageParser$Package;ZLjava/lang/String;Ljava/lang/String;Lcom/android/server/pm/permission/PermissionManagerServiceInternal$PermissionCallback;Landroid/content/pm/PackageParser$Package;)V
+Lcom/android/server/pm/permission/PermissionManagerService;->getVolumeUuidForPackage(Landroid/content/pm/PackageParser$Package;)Ljava/lang/String;
+Lcom/android/server/pm/permission/PermissionsState;->setGlobalGids([I)V
+Lcom/android/server/pm/permission/PermissionManagerService;->checkIfLegacyStorageOpsNeedToBeUpdated(Landroid/content/pm/PackageParser$Package;Z[I)[I
+Lcom/android/server/pm/permission/PermissionManagerService$1;->onPermissionUpdated([IZ)V
+Lcom/android/server/pm/PackageManagerService$PackageManagerInternalImpl;->writePermissionSettings([IZ)V
+Lcom/android/server/pm/PackageSetting;->isPrivileged()Z
+Lcom/android/server/pm/permission/BasePermission;->isPre23()Z
+Lcom/android/server/pm/permission/BasePermission;->isInstaller()Z
+Lcom/android/server/usage/AppIdleHistory;->getLongValue(Lorg/xmlpull/v1/XmlPullParser;Ljava/lang/String;J)J
+Lcom/android/server/pm/PackageManagerService;->reconcileApps(Ljava/lang/String;)V
+Lcom/android/server/usage/AppIdleHistory;->readAppIdleTimes(ILandroid/util/ArrayMap;)V
+Lcom/android/server/SystemServiceManager;->startBootPhase(Lcom/android/server/utils/TimingsTraceAndSlog;I)V
+Lcom/android/server/pm/PackageManagerService$PackageManagerInternalImpl;->getPackageList(Landroid/content/pm/PackageManagerInternal$PackageListObserver;)Landroid/content/pm/PackageList;
+Lcom/android/server/pm/PackageManagerService;->getPackagesForUid(I)[Ljava/lang/String;
+Lcom/android/server/wm/ConfigurationContainer;->getConfiguration()Landroid/content/res/Configuration;
+Lcom/android/server/am/ActivityManagerService;->enforceNotIsolatedCaller(Ljava/lang/String;)V
+Lcom/android/server/am/ActivityManagerService;->getRecordForAppLocked(Landroid/app/IApplicationThread;)Lcom/android/server/am/ProcessRecord;
+Lcom/android/server/am/ProcessList;->getLRURecordForAppLocked(Landroid/app/IApplicationThread;)Lcom/android/server/am/ProcessRecord;
+Lcom/android/server/am/ActivityManagerService;->isInstantApp(Lcom/android/server/am/ProcessRecord;Ljava/lang/String;I)Z
+Lcom/android/server/inputmethod/InputMethodUtils$InputMethodSettings;->getEnabledInputMethodSubtypeListLocked(Landroid/view/inputmethod/InputMethodInfo;)Ljava/util/List;
+Lcom/android/server/inputmethod/InputMethodSubtypeSwitchingController$InputMethodAndSubtypeList;->getSortedInputMethodAndSubtypeList(ZZ)Ljava/util/List;
+Lcom/android/server/policy/PermissionPolicyService;->getSwitchOp(Ljava/lang/String;)I
+Lcom/android/server/policy/PermissionPolicyService;->access$500(Ljava/lang/String;)I
+Lcom/android/server/policy/PermissionPolicyService$PermissionToOpSynchroniser;->addPackage(Ljava/lang/String;)V
+Lcom/android/server/pm/PackageManagerService$PackageManagerInternalImpl;->getInstantAppPackageName(I)Ljava/lang/String;
+Lcom/android/server/pm/PackageManagerService;->access$5500(Lcom/android/server/pm/PackageManagerService;I)Ljava/lang/String;
+Lcom/android/server/pm/permission/PermissionManagerService;->getPermissionInfo(Ljava/lang/String;Ljava/lang/String;I)Landroid/content/pm/PermissionInfo;
+Lcom/android/server/pm/permission/BasePermission;->getProtectionLevel()I
+Lcom/android/server/pm/permission/PermissionManagerService;->adjustPermissionProtectionFlagsLocked(ILjava/lang/String;I)I
+Lcom/android/server/pm/permission/BasePermission;->generatePermissionInfo(II)Landroid/content/pm/PermissionInfo;
+Lcom/android/server/policy/PermissionPolicyService$PermissionToOpSynchroniser;->addOpIfRestricted(Landroid/content/pm/PermissionInfo;Landroid/content/pm/PackageInfo;)V
+Lcom/android/server/policy/PermissionPolicyService$PermissionToOpSynchroniser;->addOpIfFgPermissions(Landroid/content/pm/PermissionInfo;Landroid/content/pm/PackageInfo;)V
+Lcom/android/server/pm/PackageManagerService$PackageManagerInternalImpl;->filterAppAccess(Landroid/content/pm/PackageParser$Package;II)Z
+Lcom/android/server/pm/PackageManagerService;->access$5600(Lcom/android/server/pm/PackageManagerService;Lcom/android/server/pm/PackageSetting;II)Z
+Lcom/android/server/wm/ActivityTaskManagerService;->getRecentTasks()Lcom/android/server/wm/RecentTasks;
+Lcom/android/server/pm/PackageManagerService;->isRecentsAccessingChildProfiles(II)Z
+Lcom/android/server/pm/PackageManagerService$Injector;->getActivityTaskManagerInternal()Lcom/android/server/wm/ActivityTaskManagerInternal;
+Lcom/android/server/wm/ActivityTaskManagerService$LocalService;->isCallerRecents(I)Z
+Lcom/android/server/wm/RecentTasks;->isCallerRecents(I)Z
+Lcom/android/server/pm/PackageManagerService;->getApplicationInfoInternal(Ljava/lang/String;III)Landroid/content/pm/ApplicationInfo;
+Lcom/android/server/pm/PackageManagerService;->updateFlagsForApplication(IILjava/lang/Object;)I
+Lcom/android/server/pm/PackageManagerService;->getApplicationInfo(Ljava/lang/String;II)Landroid/content/pm/ApplicationInfo;
+Lcom/android/server/pm/PackageManagerService;->getPackageInfo(Ljava/lang/String;II)Landroid/content/pm/PackageInfo;
+Lcom/android/server/pm/PackageManagerService;->getPackageInfoInternal(Ljava/lang/String;JIII)Landroid/content/pm/PackageInfo;
+Lcom/android/server/policy/SoftRestrictedPermissionPolicy;->getMinimumTargetSDK(Landroid/content/Context;Landroid/content/pm/ApplicationInfo;Landroid/os/UserHandle;)I
+Lcom/android/server/pm/permission/PermissionManagerService;->getPermissionFlags(Ljava/lang/String;Ljava/lang/String;I)I
+Lcom/android/server/pm/permission/PermissionManagerService;->getPermissionFlagsInternal(Ljava/lang/String;Ljava/lang/String;II)I
+Lcom/android/server/pm/permission/PermissionManagerService;->enforceGrantRevokeGetRuntimePermissionPermissions(Ljava/lang/String;)V
+Lcom/android/server/policy/PermissionPolicyService$PermissionToOpSynchroniser$OpToChange;-><init>(Lcom/android/server/policy/PermissionPolicyService$PermissionToOpSynchroniser;ILjava/lang/String;I)V
+Lcom/android/server/appop/AppOpsService;->getUidStateLocked(IZ)Lcom/android/server/appop/AppOpsService$UidState;
+Lcom/android/server/appop/AppOpsService;->verifyIncomingUid(I)V
+Lcom/android/server/appop/AppOpsService;->verifyIncomingOp(I)V
+Lcom/android/server/pm/UserManagerService;->hasManagedProfile(I)Z
+Lcom/android/server/appop/AppOpsService;->verifyAndGetIsPrivileged(ILjava/lang/String;)Z
+Lcom/android/server/appop/AppOpsService;->resolvePackageName(ILjava/lang/String;)Ljava/lang/String;
+Lcom/android/server/appop/AppOpsService;->isOpRestrictedLocked(IILjava/lang/String;Z)Z
+Lcom/android/server/policy/PermissionPolicyService$PermissionToOpSynchroniser;->syncPackages()V
+Lcom/android/server/appop/AppOpsService;->checkOperationInternal(IILjava/lang/String;Z)I
+Lcom/android/server/appop/AppOpsService;->checkOperationImpl(IILjava/lang/String;Z)I
+Lcom/android/server/appop/AppOpsService;->checkOperationUnchecked(IILjava/lang/String;Z)I
+Lcom/android/server/pm/permission/BasePermission;->isVerifier()Z
+Lcom/android/server/pm/permission/BasePermission;->isPreInstalled()Z
+Lcom/android/server/policy/PermissionPolicyService;->isStarted(I)Z
+Lcom/android/server/policy/PermissionPolicyService$Internal;->isInitialized(I)Z
+Lcom/android/server/policy/PermissionPolicyService;->access$100(Lcom/android/server/policy/PermissionPolicyService;I)Z
+Lcom/android/server/usage/AppStandbyController;->getIdleUidsForUser(I)[I
+Lcom/android/server/pm/PackageManagerService;->getInstalledApplicationsListInternal(III)Ljava/util/List;
+Lcom/android/server/am/ProcessRecord;->getCurProcState()I
+Lcom/android/server/connectivity/PermissionMonitor;->hasPermission(Landroid/content/pm/PackageInfo;Ljava/lang/String;)Z
+Lcom/android/server/connectivity/PermissionMonitor;->getNetdPermissionMask([Ljava/lang/String;[I)I
+Lcom/android/server/usage/AppStandbyController;->isAppIdleFiltered(Ljava/lang/String;IIJ)Z
+Lcom/android/server/usage/AppStandbyController;->isAppSpecial(Ljava/lang/String;II)Z
+Lcom/android/server/pm/PackageManagerService$PackageManagerInternalImpl;->getPackage(I)Landroid/content/pm/PackageParser$Package;
+Lcom/android/server/usage/AppStandbyController$Injector;->isPowerSaveWhitelistExceptIdleApp(Ljava/lang/String;)Z
+Lcom/android/server/DeviceIdleController$BinderService;->isPowerSaveWhitelistExceptIdleApp(Ljava/lang/String;)Z
+Lcom/android/server/DeviceIdleController;->isPowerSaveWhitelistExceptIdleAppInternal(Ljava/lang/String;)Z
+Lcom/android/server/usage/AppIdleHistory;->getUserHistory(I)Landroid/util/ArrayMap;
+Lcom/android/server/usage/AppIdleHistory;->getPackageHistory(Landroid/util/ArrayMap;Ljava/lang/String;JZ)Lcom/android/server/usage/AppIdleHistory$AppUsageHistory;
+Lcom/android/server/net/NetworkPolicyManagerService;->updateRulesForAllAppsUL(I)V
+Lcom/android/server/pm/permission/PermissionManagerService;->checkUidPermission(Ljava/lang/String;I)I
+Lcom/android/server/pm/permission/PermissionManagerService;->checkUidPermissionImpl(Ljava/lang/String;I)I
+Lcom/android/server/pm/permission/PermissionManagerService;->checkUidPermissionInternal(Ljava/lang/String;Landroid/content/pm/PackageParser$Package;II)I
+Lcom/android/server/pm/PackageManagerService;->checkUidPermission(Ljava/lang/String;I)I
+Lcom/android/server/net/NetworkPolicyManagerService;->hasInternetPermissions(I)Z
+Lcom/android/server/pm/permission/PermissionManagerService;->isImpliedPermissionGranted(Lcom/android/server/pm/permission/PermissionsState;Ljava/lang/String;I)Z
+Lcom/android/server/pm/PackageManagerService;->resolveContentProvider(Ljava/lang/String;II)Landroid/content/pm/ProviderInfo;
+Lcom/android/server/pm/PackageManagerService;->resolveContentProviderInternal(Ljava/lang/String;II)Landroid/content/pm/ProviderInfo;
+Lcom/android/server/pm/ComponentResolver;->queryProvider(Ljava/lang/String;II)Landroid/content/pm/ProviderInfo;
+Lcom/android/server/am/OomAdjuster;->updateOomAdjLocked(Ljava/lang/String;)V
+Lcom/android/server/am/BroadcastFilter;-><init>(Landroid/content/IntentFilter;Lcom/android/server/am/ReceiverList;Ljava/lang/String;Ljava/lang/String;IIZZ)V
+Lcom/android/server/am/ActivityManagerService$PidMap;->get(I)Lcom/android/server/am/ProcessRecord;
+Lcom/android/server/am/UidRecord;->getCurProcState()I
+Lcom/android/server/am/ActivityManagerService;->checkContentProviderPermissionLocked(Landroid/content/pm/ProviderInfo;Lcom/android/server/am/ProcessRecord;IZ)Ljava/lang/String;
+Lcom/android/server/am/ActiveUids;->valueAt(I)Lcom/android/server/am/UidRecord;
+Lcom/android/server/NetworkManagementService;->getFirewallChainState(I)Z
+Lcom/android/server/pm/ComponentResolver;->access$800()Lcom/android/server/pm/UserManagerService;
+Lcom/android/server/content/ContentService;->handleIncomingUser(Landroid/net/Uri;IIIZI)I
+Lcom/android/server/am/ActivityManagerService$LocalService;->checkContentProviderAccess(Ljava/lang/String;I)Ljava/lang/String;
+Lcom/android/server/am/ActivityManagerService;->checkContentProviderAccess(Ljava/lang/String;I)Ljava/lang/String;
+Lcom/android/server/content/ContentService;->registerContentObserver(Landroid/net/Uri;ZLandroid/database/IContentObserver;II)V
+Lcom/android/server/content/ContentService$ObserverNode;->addObserverLocked(Landroid/net/Uri;Landroid/database/IContentObserver;ZLjava/lang/Object;III)V
+Lcom/android/server/content/ContentService$ObserverNode$ObserverEntry;-><init>(Lcom/android/server/content/ContentService$ObserverNode;Landroid/database/IContentObserver;ZLjava/lang/Object;IIILandroid/net/Uri;)V
+Lcom/android/server/content/ContentService;->access$300()Lcom/android/internal/os/BinderDeathDispatcher;
+Lcom/android/server/am/ProcessRecord;->setCurRawAdj(I)V
+Lcom/android/server/wm/WindowProcessController;->setPerceptible(Z)V
+Lcom/android/server/am/OomAdjuster;->computeOomAdjLocked(Lcom/android/server/am/ProcessRecord;ILcom/android/server/am/ProcessRecord;ZJZ)Z
+Lcom/android/server/am/UidRecord;->setCurProcState(I)V
+Lcom/android/server/am/ProcessRecord;->setCurRawProcState(I)V
+Lcom/android/server/location/GnssConfiguration;->loadPropertiesFromCarrierConfig()V
+Lcom/android/server/LockGuard;->guard(I)V
+Lcom/android/server/role/RoleManagerService;->lambda$computeComponentStateHash$2(Ljava/io/ByteArrayOutputStream;Landroid/content/pm/PackageManagerInternal;ILandroid/content/pm/PackageParser$Package;)V
+Lcom/android/server/wm/ActivityStack;->topRunningActivityLocked(Z)Lcom/android/server/wm/ActivityRecord;
+Lcom/android/server/pm/UserManagerService;->getUserInfoLU(I)Landroid/content/pm/UserInfo;
+Lcom/android/server/wm/RootActivityContainer;->getActivityDisplay(I)Lcom/android/server/wm/ActivityDisplay;
+Lcom/android/server/wm/ActivityStack;->getDisplay()Lcom/android/server/wm/ActivityDisplay;
+Lcom/android/server/wm/ConfigurationContainer;->getActivityType()I
+Lcom/android/server/wm/ActivityStack;->topRunningActivityLocked()Lcom/android/server/wm/ActivityRecord;
+Lcom/android/server/wm/WindowContainer;->forAllWindows(Lcom/android/internal/util/ToBooleanFunction;Z)Z
+Lcom/android/server/wm/WindowContainer;->getDisplayContent()Lcom/android/server/wm/DisplayContent;
+Lcom/android/server/am/ActivityManagerService$4;->allowFilterResult(Lcom/android/server/am/BroadcastFilter;Ljava/util/List;)Z
+Lcom/android/server/am/ProcessRecord;->getWindowProcessController()Lcom/android/server/wm/WindowProcessController;
+Lcom/android/server/usage/AppStandbyController;->isActiveDeviceAdmin(Ljava/lang/String;I)Z
+Lcom/android/server/usage/AppStandbyController;->isActiveNetworkScorer(Ljava/lang/String;)Z
+Lcom/android/server/usage/AppStandbyController$Injector;->getActiveNetworkScorer()Ljava/lang/String;
+Lcom/android/server/NetworkScoreService;->getActiveScorerPackage()Ljava/lang/String;
+Lcom/android/server/NetworkScoreService;->enforceSystemOrHasScoreNetworks()V
+Lcom/android/server/usage/AppStandbyController$Injector;->isBoundWidgetPackage(Landroid/appwidget/AppWidgetManager;Ljava/lang/String;I)Z
+Lcom/android/server/appwidget/AppWidgetServiceImpl;->isBoundWidgetPackage(Ljava/lang/String;I)Z
+Lcom/android/server/usage/AppStandbyController;->isDeviceProvisioningPackage(Ljava/lang/String;)Z
+Lcom/android/server/usage/AppStandbyController;->isCarrierApp(Ljava/lang/String;)Z
+Lcom/android/server/usage/AppIdleHistory;->getThresholdIndex(Ljava/lang/String;IJ[J[J)I
+Lcom/android/server/usage/AppIdleHistory;->getElapsedTime(J)J
+Lcom/android/server/usage/AppIdleHistory;->isIdle(Ljava/lang/String;IJ)Z
+Lcom/android/server/net/NetworkPolicyManagerService;->isUidValidForBlacklistRules(I)Z
+Lcom/android/server/net/NetworkPolicyManagerService;->updateRulesForPowerRestrictionsUL(IIZ)I
+Lcom/android/server/net/NetworkPolicyManagerService;->updateRulesForPowerRestrictionsULInner(IIZ)I
+Lcom/android/server/net/NetworkPolicyManagerService;->updateRulesForPowerRestrictionsUL(I)V
+Lcom/android/server/usage/AppStandbyController;->isAppIdleUnfiltered(Ljava/lang/String;IJ)Z
+Lcom/android/server/usage/AppStandbyController;->informListeners(Ljava/lang/String;IIIZ)V
+Lcom/android/server/am/ActivityManagerService;->dispatchUidsChangedForObserver(Landroid/app/IUidObserver;Lcom/android/server/am/ActivityManagerService$UidObserverRegistration;I)V
+Lcom/android/server/pm/PackageManagerService;->getPackageUid(Ljava/lang/String;II)I
+Lcom/android/server/am/ProcessRecord;->getCurRawAdj()I
+Lcom/android/server/am/ProcessRecord;->getReportedProcState()I
+Lcom/android/server/usage/UserUsageStatsService;->reportEvent(Landroid/app/usage/UsageEvents$Event;)V
+Lcom/android/server/usage/IntervalStats;->update(Ljava/lang/String;Ljava/lang/String;JII)V
+Lcom/android/server/BinderCallsStatsService$AuthorizedWorkSourceProvider;->resolveWorkSourceUid(I)I
+Lcom/android/server/BinderCallsStatsService$AuthorizedWorkSourceProvider;->getCallingUid()I
+Lcom/android/server/wm/WindowContainer;->getParent()Lcom/android/server/wm/WindowContainer;
+Lcom/android/server/wm/WindowContainer;->scheduleAnimation()V
+Lcom/android/server/wm/ConfigurationContainer;->getBounds()Landroid/graphics/Rect;
+Lcom/android/server/wm/DisplayContent;->forAllWindows(Lcom/android/internal/util/ToBooleanFunction;Z)Z
+Lcom/android/server/wm/WindowContainer;->getPendingTransaction()Landroid/view/SurfaceControl$Transaction;
+Lcom/android/server/wm/DisplayContent;->skipTraverseChild(Lcom/android/server/wm/WindowContainer;)Z
+Lcom/android/server/am/ActivityManagerService;->incrementProcStateSeqAndNotifyAppsLocked()V
+Lcom/android/server/wm/WindowManagerService;->boostPriorityForLockedSection()V
+Lcom/android/server/wm/WindowManagerThreadPriorityBooster;->boost()V
+Lcom/android/server/wm/WindowManagerService;->resetPriorityAfterLockedSection()V
+Lcom/android/server/wm/WindowManagerThreadPriorityBooster;->reset()V
+Lcom/android/server/IntentResolver;->filterResults(Ljava/util/List;)V
+Lcom/android/server/IntentResolver;->getFastIntentCategories(Landroid/content/Intent;)Landroid/util/FastImmutableArraySet;
+Lcom/android/server/am/ProcessRecord;->getCurrentSchedulingGroup()I
+Lcom/android/server/content/ContentService$ObserverNode;->collectObserversLocked(Landroid/net/Uri;ILandroid/database/IContentObserver;ZIILjava/util/ArrayList;)V
+Lcom/android/server/display/LogicalDisplay;->getDisplayInfoLocked()Landroid/view/DisplayInfo;
+Lcom/android/server/am/UidRecord;->reset()V
+Lcom/android/server/am/ActivityManagerService;->isReceivingBroadcastLocked(Lcom/android/server/am/ProcessRecord;Landroid/util/ArraySet;)Z
+Lcom/android/server/am/ProcessRecord;->hasForegroundServices()Z
+Lcom/android/server/wm/WindowContainer;->prepareSurfaces()V
+Lcom/android/server/am/ReceiverList;-><init>(Lcom/android/server/am/ActivityManagerService;Lcom/android/server/am/ProcessRecord;IIILandroid/content/IIntentReceiver;)V
+Lcom/android/server/am/ReceiverList;->hashCode()I
+Lcom/android/server/display/DisplayManagerService;->access$1600(Lcom/android/server/display/DisplayManagerService;II)Landroid/view/DisplayInfo;
+Lcom/android/server/display/DisplayManagerService;->getDisplayInfoInternal(II)Landroid/view/DisplayInfo;
+Lcom/android/server/display/DisplayManagerService$BinderService;->getDisplayInfo(I)Landroid/view/DisplayInfo;
+Lcom/android/server/am/ActivityManagerService$Injector;->isNetworkRestrictedForUid(I)Z
+Lcom/android/server/am/ActivityManagerService$Injector;->ensureHasNetworkManagementInternal()Z
+Lcom/android/server/NetworkManagementService$LocalService;->isNetworkRestrictedForUid(I)Z
+Lcom/android/server/NetworkManagementService;->access$1400(Lcom/android/server/NetworkManagementService;I)Z
+Lcom/android/server/NetworkManagementService;->isNetworkRestrictedInternal(I)Z
+Lcom/android/server/wm/ConfigurationContainer;->getWindowingMode()I
+Lcom/android/server/wm/WindowContainer;->isSelfOrChildAnimating()Z
+Lcom/android/server/am/ProcessRecord;->setCurrentSchedulingGroup(I)V
+Lcom/android/server/wm/WindowProcessController;->setCurrentSchedulingGroup(I)V
+Lcom/android/server/IntentResolver;->queryIntent(Landroid/content/Intent;Ljava/lang/String;ZI)Ljava/util/List;
+Lcom/android/server/am/ProcessRecord;->hasForegroundActivities()Z
+Lcom/android/server/wm/WindowState;->getDisplayContent()Lcom/android/server/wm/DisplayContent;
+Lcom/android/server/pm/ComponentResolver;->access$900()Landroid/content/pm/PackageManagerInternal;
+Lcom/android/server/wm/SurfaceAnimator;->hasLeash()Z
+Lcom/android/server/wm/WindowContainer;->checkCompleteDeferredRemoval()Z
+Lcom/android/server/wm/WindowContainer;->isSelfAnimating()Z
+Lcom/android/server/wm/SurfaceAnimator;->isAnimating()Z
+Lcom/android/server/wm/DisplayContent;->getDisplayId()I
+Lcom/android/server/am/ProcessRecord;->setHasForegroundActivities(Z)V
+Lcom/android/server/wm/WindowProcessController;->setHasForegroundActivities(Z)V
+Lcom/android/server/am/ProcessRecord;->setCurProcState(I)V
+Lcom/android/server/wm/WindowProcessController;->setCurrentProcState(I)V
+Lcom/android/server/am/ActivityManagerService;->updateLowMemStateLocked(III)Z
+Lcom/android/server/wm/ConfigurationContainer;->getWindowConfiguration()Landroid/app/WindowConfiguration;
+Lcom/android/server/am/OomAdjuster;->applyOomAdjLocked(Lcom/android/server/am/ProcessRecord;ZJJ)Z
+Lcom/android/server/am/AppCompactor;->useCompaction()Z
+Lcom/android/server/am/ProcessList;->procStatesDifferForMem(II)Z
+Lcom/android/server/am/ActivityManagerService;->dispatchUidsChanged()V
+Lcom/android/server/audio/AudioService$VolumeStreamState;->setIndex(IILjava/lang/String;)Z
+Lcom/android/server/audio/AudioService;->access$3000(Lcom/android/server/audio/AudioService;)[Lcom/android/server/audio/AudioService$VolumeStreamState;
+Lcom/android/server/content/ContentService$ObserverNode;->removeObserverLocked(Landroid/database/IContentObserver;)Z
+Lcom/android/server/wm/DisplayContent$TaskStackContainers;->forAllExitingAppTokenWindows(Lcom/android/internal/util/ToBooleanFunction;Z)Z
+Lcom/android/server/wm/WindowState;->getTask()Lcom/android/server/wm/Task;
+Lcom/android/server/appop/AppOpsService;->getOpLocked(IILjava/lang/String;ZZ)Lcom/android/server/appop/AppOpsService$Op;
+Lcom/android/server/appop/AppOpsService;->getOpsRawNoVerifyLocked(ILjava/lang/String;ZZ)Lcom/android/server/appop/AppOpsService$Ops;
+Lcom/android/server/wm/AppWindowToken;->getTask()Lcom/android/server/wm/Task;
+Lcom/android/server/wm/WindowContainer;->checkAppWindowsReadyToShow()V
+Lcom/android/server/SystemService;->getContext()Landroid/content/Context;
+Lcom/android/server/am/ProcessRecord;->getInteractionEventTime()J
+Lcom/android/server/power/PowerManagerService;->findWakeLockIndexLocked(Landroid/os/IBinder;)I
+Lcom/android/server/power/PowerManagerService;->updateWakeLockSummaryLocked(I)V
+Lcom/android/server/pm/PackageManagerService$PackageManagerInternalImpl;->isEnabledAndMatches(Landroid/content/pm/ComponentInfo;II)Z
+Lcom/android/server/wm/ConfigurationContainer;->onConfigurationChanged(Landroid/content/res/Configuration;)V
+Lcom/android/server/policy/SoftRestrictedPermissionPolicy;->forPermission(Landroid/content/Context;Landroid/content/pm/ApplicationInfo;Landroid/os/UserHandle;Ljava/lang/String;)Lcom/android/server/policy/SoftRestrictedPermissionPolicy;
+Lcom/android/server/appop/AppOpsService;->checkOperationRaw(IILjava/lang/String;)I
+Lcom/android/server/appop/AppOpsService;->getOpLocked(Lcom/android/server/appop/AppOpsService$Ops;IZ)Lcom/android/server/appop/AppOpsService$Op;
+Lcom/android/server/policy/PermissionPolicyService$PermissionToOpSynchroniser;->setUidModeIfMode(IIIILjava/lang/String;)Z
+Lcom/android/server/policy/PermissionPolicyService$PermissionToOpSynchroniser;->setUidModeAllowedIfDefault(IILjava/lang/String;)Z
+Lcom/android/server/pm/PackageManagerService;->getPackagesForSharedUserIdLocked(Ljava/lang/String;I)[Ljava/lang/String;
+Lcom/android/server/policy/PermissionPolicyService;->synchronizePackagePermissionsAndAppOpsForUser(Ljava/lang/String;I)V
+Lcom/android/server/am/ActivityManagerService;->getPackageManagerInternalLocked()Landroid/content/pm/PackageManagerInternal;
+Lcom/android/server/power/PowerManagerService;->getWakeLockSummaryFlags(Lcom/android/server/power/PowerManagerService$WakeLock;)I
+Lcom/android/server/TelephonyRegistry;->add(Landroid/os/IBinder;)Lcom/android/server/TelephonyRegistry$Record;
+Lcom/android/server/am/ServiceRecord;->getConnections()Landroid/util/ArrayMap;
+Lcom/android/server/am/ProcessRecord;->hasTopUi()Z
+Lcom/android/server/wm/WindowProcessController;->hasVisibleActivities()Z
+Lcom/android/server/am/ActivityManagerService;->onTransact(ILandroid/os/Parcel;Landroid/os/Parcel;I)Z
+Lcom/android/server/am/ProcessRecord;->hasPendingUiClean()Z
+Lcom/android/server/am/UserController;->getStartedUserState(I)Lcom/android/server/am/UserState;
+Lcom/android/server/wm/ConfigurationContainer;->inSplitScreenPrimaryWindowingMode()Z
+Lcom/android/server/wm/ActivityDisplay;->getFocusedStack()Lcom/android/server/wm/ActivityStack;
+Lcom/android/server/pm/dex/DexManager$PackageCodeLocations;->searchDex(Ljava/lang/String;I)I
+Lcom/android/server/pm/dex/DexManager;->getDexPackage(Landroid/content/pm/ApplicationInfo;Ljava/lang/String;I)Lcom/android/server/pm/dex/DexManager$DexSearchResult;
+Lcom/android/server/pm/PackageManagerService;->updateFlagsForResolve(IILandroid/content/Intent;IZZ)I
+Lcom/android/server/wm/WindowState;->getParentWindow()Lcom/android/server/wm/WindowState;
+Lcom/android/server/TelephonyRegistry$Record;->matchPhoneStateListenerEvent(I)Z
+Lcom/android/server/wm/WindowState;->forAllWindows(Lcom/android/internal/util/ToBooleanFunction;Z)Z
+Lcom/android/server/wm/WindowState;->applyInOrderWithImeWindows(Lcom/android/internal/util/ToBooleanFunction;Z)Z
+Lcom/android/server/wm/WindowState;->applyImeWindowsIfNeeded(Lcom/android/internal/util/ToBooleanFunction;Z)Z
+Lcom/android/server/wm/WindowState;->isInputMethodTarget()Z
+Lcom/android/server/wm/WindowContainer;->getChildCount()I
+Lcom/android/server/am/ProcessRecord;->getActiveInstrumentation()Lcom/android/server/am/ActiveInstrumentation;
+Lcom/android/server/am/ProcessRecord;->modifyRawOomAdj(I)I
+Lcom/android/server/wm/WindowAnimator;->scheduleAnimation()V
+Lcom/android/server/wm/WindowContainer$ForAllWindowsConsumerWrapper;->apply(Ljava/lang/Object;)Z
+Lcom/android/server/wm/WindowContainer$ForAllWindowsConsumerWrapper;->apply(Lcom/android/server/wm/WindowState;)Z
+Lcom/android/server/wm/RootWindowContainer;->getDisplayContent(I)Lcom/android/server/wm/DisplayContent;
+Lcom/android/server/wm/ActivityTaskManagerService$LocalService;->getTopProcessState()I
+Lcom/android/server/wm/ActivityTaskManagerService$LocalService;->isHeavyWeightProcess(Lcom/android/server/wm/WindowProcessController;)Z
+Lcom/android/server/wm/WindowProcessController;->isHomeProcess()Z
+Lcom/android/server/wm/WindowProcessController;->isPreviousProcess()Z
+Lcom/android/server/pm/PackageManagerService;->updateFlagsForResolve(IILandroid/content/Intent;IZ)I
+Lcom/android/server/am/BroadcastQueue;->processNextBroadcastLocked(ZZ)V
+Lcom/android/server/am/ActivityManagerService;->ensureAllowedAssociations()V
+Lcom/android/server/am/ActivityManagerService;->validateAssociationAllowedLocked(Ljava/lang/String;ILjava/lang/String;I)Z
+Lcom/android/server/StorageManagerService;->isUserKeyUnlocked(I)Z
+Lcom/android/server/am/ProcessRecord;->hasOverlayUi()Z
+Lcom/android/server/am/ContentProviderRecord;->hasExternalProcessHandles()Z
+Lcom/android/server/am/UserController;->isUserRunning(II)Z
+Lcom/android/server/wm/RootActivityContainer;->isFocusable(Lcom/android/server/wm/ConfigurationContainer;Z)Z
+Lcom/android/server/wm/WindowProcessController;->hasActivities()Z
+Lcom/android/server/wm/WindowState;->getAttrs()Landroid/view/WindowManager$LayoutParams;
+Lcom/android/server/am/ProcessRecord$PackageList;->containsKey(Ljava/lang/Object;)Z
+Lcom/android/server/wm/ActivityDisplay;->getChildCount()I
+Lcom/android/server/TelephonyRegistry;->notifyDataConnectionForSubscriber(IIIZLjava/lang/String;Ljava/lang/String;Landroid/net/LinkProperties;Landroid/net/NetworkCapabilities;IZ)V
+Lcom/android/server/am/OomAdjuster;->shouldSkipDueToCycle(Lcom/android/server/am/ProcessRecord;Lcom/android/server/am/ProcessRecord;IIZ)Z
+Lcom/android/server/am/ProcessRecord;->getCurRawProcState()I
+Lcom/android/server/am/ConnectionRecord;->trackProcState(IIJ)V
+Lcom/android/server/wm/ActivityStack;->getResumedActivity()Lcom/android/server/wm/ActivityRecord;
+Lcom/android/server/wm/ActivityStackSupervisor;->isCurrentProfileLocked(I)Z
+Lcom/android/server/wm/ActivityRecord;->okToShowLocked()Z
+Lcom/android/server/am/ActivityManagerService$LocalService;->isUserRunning(II)Z
+Lcom/android/server/am/ProcessRecord;->hasRecentTasks()Z
+Lcom/android/server/wm/WindowProcessController;->hasRecentTasks()Z
+Lcom/android/server/am/ConnectionRecord;->hasFlag(I)Z
+Lcom/android/server/am/ActiveServices;->updateServiceClientActivitiesLocked(Lcom/android/server/am/ProcessRecord;Lcom/android/server/am/ConnectionRecord;Z)Z
+Lcom/android/server/pm/PackageManagerService$PackageManagerInternalImpl;->isPermissionsReviewRequired(Ljava/lang/String;I)Z
+Lcom/android/server/pm/PackageManagerService;->access$5900(Lcom/android/server/pm/PackageManagerService;)Lcom/android/server/pm/permission/PermissionManagerServiceInternal;
+Lcom/android/server/pm/permission/PermissionManagerService$PermissionManagerServiceInternalImpl;->isPermissionsReviewRequired(Landroid/content/pm/PackageParser$Package;I)Z
+Lcom/android/server/pm/permission/PermissionManagerService;->access$600(Lcom/android/server/pm/permission/PermissionManagerService;Landroid/content/pm/PackageParser$Package;I)Z
+Lcom/android/server/pm/permission/PermissionManagerService;->isPermissionsReviewRequired(Landroid/content/pm/PackageParser$Package;I)Z
+Lcom/android/server/am/ProcessRecord;->updateBoundClientUids()V
+Lcom/android/server/firewall/IntentFirewall;->checkIntent(Lcom/android/server/firewall/IntentFirewall$FirewallIntentResolver;Landroid/content/ComponentName;ILandroid/content/Intent;IILjava/lang/String;I)Z
+Lcom/android/server/firewall/IntentFirewall$FirewallIntentResolver;->queryByComponent(Landroid/content/ComponentName;Ljava/util/List;)V
+Lcom/android/server/pm/permission/PermissionManagerService;->checkPermission(Ljava/lang/String;Ljava/lang/String;I)I
+Lcom/android/server/pm/permission/PermissionManagerService;->checkPermissionImpl(Ljava/lang/String;Ljava/lang/String;I)I
+Lcom/android/server/pm/permission/PermissionManagerService;->checkPermissionInternal(Ljava/lang/String;Ljava/lang/String;II)I
+Lcom/android/server/am/ActivityManagerService;->checkTime(JLjava/lang/String;)V
+Lcom/android/server/wm/ActivityDisplay;->getChildAt(I)Lcom/android/server/wm/ActivityStack;
+Lcom/android/server/power/PowerManagerService;->access$3700(Lcom/android/server/power/PowerManagerService;)Landroid/content/Context;
+Lcom/android/server/appop/AppOpsService;->checkPackage(ILjava/lang/String;)I
+Lcom/android/server/am/BroadcastQueue;->deliverToRegisteredReceiverLocked(Lcom/android/server/am/BroadcastRecord;Lcom/android/server/am/BroadcastFilter;ZI)V
+Lcom/android/server/am/ProcessList;->checkSlow(JLjava/lang/String;)V
+Lcom/android/server/pm/ComponentResolver$ActivityIntentResolver;->isFilterStopped(Landroid/content/IntentFilter;I)Z
+Lcom/android/server/pm/ComponentResolver$ActivityIntentResolver;->isFilterStopped(Landroid/content/pm/PackageParser$ActivityIntentInfo;I)Z
+Lcom/android/server/wm/ConfigurationContainer;->inPinnedWindowingMode()Z
+Lcom/android/server/am/ActiveUids;->size()I
+Lcom/android/server/wm/TaskRecord;->topRunningActivityLocked()Lcom/android/server/wm/ActivityRecord;
+Lcom/android/server/firewall/IntentFirewall$FirewallIntentResolver;->sortResults(Ljava/util/List;)V
+Lcom/android/server/pm/PackageManagerService;->onTransact(ILandroid/os/Parcel;Landroid/os/Parcel;I)Z
+Lcom/android/server/wm/WindowContainer;->isAnimating()Z
+Lcom/android/server/wm/WindowContainer;->getDisplayedBounds()Landroid/graphics/Rect;
+Lcom/android/server/wm/WindowManagerService;->scheduleAnimationLocked()V
+Lcom/android/server/wm/Dimmer;->resetDimStates()V
+Lcom/android/server/wm/Dimmer;->updateDims(Landroid/view/SurfaceControl$Transaction;Landroid/graphics/Rect;)Z
+Lcom/android/server/wm/WindowState;->wouldBeVisibleIfPolicyIgnored()Z
+Lcom/android/server/firewall/IntentFirewall;->checkBroadcast(Landroid/content/Intent;IILjava/lang/String;I)Z
+Lcom/android/server/am/BroadcastQueue;->requestStartTargetPermissionsReviewIfNeededLocked(Lcom/android/server/am/BroadcastRecord;Ljava/lang/String;I)Z
+Lcom/android/server/wm/WindowState;->isParentWindowHidden()Z
+Lcom/android/server/wm/WindowStateAnimator;->hasSurface()Z
+Lcom/android/server/wm/WindowContainer;->getDimmer()Lcom/android/server/wm/Dimmer;
+Lcom/android/server/power/batterysaver/BatterySaverPolicy;->getCurrentPolicyLocked()Lcom/android/server/power/batterysaver/BatterySaverPolicy$Policy;
+Lcom/android/server/power/batterysaver/BatterySaverPolicy;->getBatterySaverPolicy(I)Landroid/os/PowerSaveState;
+Lcom/android/server/power/Notifier;->getBatteryStatsWakeLockMonitorType(I)I
+Lcom/android/server/display/DisplayManagerService;->access$600(Lcom/android/server/display/DisplayManagerService;)Lcom/android/server/display/DisplayManagerService$SyncRoot;
+Lcom/android/server/power/PowerManagerService;->updatePowerStateLocked()V
+Lcom/android/server/am/BatteryStatsService;->enforceCallingPermission()V
+Lcom/android/server/power/PowerManagerService;->isMaximumScreenOffTimeoutFromDeviceAdminEnforcedLocked()Z
+Lcom/android/server/wm/WindowState;->isVisible()Z
+Lcom/android/server/power/PowerManagerService;->updateIsPoweredLocked(I)V
+Lcom/android/server/power/PowerManagerService;->updateStayOnLocked(I)V
+Lcom/android/server/power/PowerManagerService;->updateScreenBrightnessBoostLocked(I)V
+Lcom/android/server/power/PowerManagerService;->updateUserActivitySummaryLocked(JI)V
+Lcom/android/server/power/PowerManagerService;->updateWakefulnessLocked(I)Z
+Lcom/android/server/power/PowerManagerService;->updateProfilesLocked(J)V
+Lcom/android/server/power/PowerManagerService;->updateDisplayPowerStateLocked(I)Z
+Lcom/android/server/power/PowerManagerService;->updateDreamLocked(IZ)V
+Lcom/android/server/power/PowerManagerService;->finishWakefulnessChangeIfNeededLocked()V
+Lcom/android/server/power/PowerManagerService;->updateSuspendBlockerLocked()V
+Lcom/android/server/power/PowerManagerService;->needDisplaySuspendBlockerLocked()Z
+Lcom/android/server/power/PowerManagerService;->setHalAutoSuspendModeLocked(Z)V
+Lcom/android/server/power/PowerManagerService;->setHalInteractiveModeLocked(Z)V
+Lcom/android/server/display/DisplayManagerService;->access$3900(Lcom/android/server/display/DisplayManagerService;)Lcom/android/server/display/DisplayPowerController;
+Lcom/android/server/power/PowerManagerService;->scheduleSandmanLocked()V
+Lcom/android/server/appop/AppOpsService;->scheduleWriteLocked()V
+Lcom/android/server/power/PowerManagerService;->getDesiredScreenPolicyLocked()I
+Lcom/android/server/power/PowerManagerService;->shouldUseProximitySensorLocked()Z
+Lcom/android/server/power/PowerManagerService;->shouldBoostScreenBrightness()Z
+Lcom/android/server/power/PowerManagerService;->updatePowerRequestFromBatterySaverPolicy(Landroid/hardware/display/DisplayManagerInternal$DisplayPowerRequest;)V
+Lcom/android/server/display/DisplayManagerService$LocalService;->requestPowerState(Landroid/hardware/display/DisplayManagerInternal$DisplayPowerRequest;Z)Z
+Lcom/android/server/display/DisplayPowerController;->requestPowerState(Landroid/hardware/display/DisplayManagerInternal$DisplayPowerRequest;Z)Z
+Lcom/android/server/power/PowerManagerService$PowerManagerHandler;->handleMessage(Landroid/os/Message;)V
+Lcom/android/server/power/PowerManagerService;->access$3100(Lcom/android/server/power/PowerManagerService;)V
+Lcom/android/server/power/PowerManagerService;->handleSandman()V
+Lcom/android/server/dreams/DreamManagerService$LocalService;->isDreaming()Z
+Lcom/android/server/dreams/DreamManagerService;->access$1400(Lcom/android/server/dreams/DreamManagerService;)Z
+Lcom/android/server/dreams/DreamManagerService;->isDreamingInternal()Z
+Lcom/android/server/power/PowerManagerService;->getSleepTimeoutLocked()J
+Lcom/android/server/power/PowerManagerService;->getScreenOffTimeoutLocked(J)J
+Lcom/android/server/power/PowerManagerService;->getScreenDimDurationLocked(J)J
+Lcom/android/server/power/PowerManagerService;->getNextProfileTimeoutLocked(J)J
+Lcom/android/server/power/PowerManagerService;->adjustWakeLockSummaryLocked(I)I
+Lcom/android/server/power/PowerManagerService;->isItBedTimeYetLocked()Z
+Lcom/android/server/wm/WindowContainer;->assignChildLayers(Landroid/view/SurfaceControl$Transaction;)V
+Lcom/android/server/wm/WindowState;->isDrawnLw()Z
+Lcom/android/server/wm/DisplayContent;->getDisplayPolicy()Lcom/android/server/wm/DisplayPolicy;
+Lcom/android/server/wm/WindowState;->isVisibleByPolicy()Z
+Lcom/android/server/wm/WindowState;->inSizeCompatMode()Z
+Lcom/android/server/wm/DisplayContent$TaskStackContainers;->forAllWindows(Lcom/android/internal/util/ToBooleanFunction;Z)Z
+Lcom/android/server/am/BroadcastQueue;->maybeAddAllowBackgroundActivityStartsToken(Lcom/android/server/am/ProcessRecord;Lcom/android/server/am/BroadcastRecord;)V
+Lcom/android/server/wm/ConfigurationContainer;->inFreeformWindowingMode()Z
+Lcom/android/server/wm/RootActivityContainer;->getTopResumedActivity()Lcom/android/server/wm/ActivityRecord;
+Lcom/android/server/wm/WindowState;->isChildWindow()Z
+Lcom/android/server/pm/PackageManagerService;->applyPostResolutionFilter(Ljava/util/List;Ljava/lang/String;ZIZILandroid/content/Intent;)Ljava/util/List;
+Lcom/android/server/locksettings/LockSettingsService;->checkReadPermission(Ljava/lang/String;I)V
+Lcom/android/server/wm/ConfigurationContainer;->getBounds(Landroid/graphics/Rect;)V
+Lcom/android/server/wm/WindowState;->getFrameLw()Landroid/graphics/Rect;
+Lcom/android/server/wm/WindowState;->isDisplayedLw()Z
+Lcom/android/server/wm/TaskStack;->getStackOutset()I
+Lcom/android/server/wm/WindowState;->getDisplayId()I
+Lcom/android/server/wm/WindowState;->getOrientationChanging()Z
+Lcom/android/server/wm/WindowContainer;->forAllWindows(Ljava/util/function/Consumer;Z)V
+Lcom/android/server/wm/WindowContainer;->obtainConsumerWrapper(Ljava/util/function/Consumer;)Lcom/android/server/wm/WindowContainer$ForAllWindowsConsumerWrapper;
+Lcom/android/server/wm/WindowContainer$ForAllWindowsConsumerWrapper;->setConsumer(Ljava/util/function/Consumer;)V
+Lcom/android/server/wm/WindowContainer$ForAllWindowsConsumerWrapper;->release()V
+Lcom/android/server/wm/WindowContainer;->access$100(Lcom/android/server/wm/WindowContainer;)Landroid/util/Pools$SynchronizedPool;
+Lcom/android/server/wm/WindowState;->updateSurfacePosition()V
+Lcom/android/server/wm/WindowState;->updateSurfacePosition(Landroid/view/SurfaceControl$Transaction;)V
+Lcom/android/server/appop/AppOpsService$UidState;->evalMode(II)I
+Lcom/android/server/power/PowerManagerService;->access$3300(Landroid/os/WorkSource;)Landroid/os/WorkSource;
+Lcom/android/server/power/PowerManagerService;->copyWorkSource(Landroid/os/WorkSource;)Landroid/os/WorkSource;
+Lcom/android/server/power/Notifier;->onWakeLockAcquired(ILjava/lang/String;Ljava/lang/String;IILandroid/os/WorkSource;Ljava/lang/String;)V
+Lcom/android/server/power/PowerManagerService;->restartNofifyLongTimerLocked(Lcom/android/server/power/PowerManagerService$WakeLock;)V
+Lcom/android/server/am/ProcessRecord;->isCrashing()Z
+Lcom/android/server/wm/WindowToken;->isHidden()Z
+Lcom/android/server/wm/AppWindowToken;->forAllWindows(Lcom/android/internal/util/ToBooleanFunction;Z)Z
+Lcom/android/server/wm/AppWindowToken;->forAllWindowsUnchecked(Lcom/android/internal/util/ToBooleanFunction;Z)Z
+Lcom/android/server/wm/WindowState;->transformFrameToSurfacePosition(IILandroid/graphics/Point;)V
+Lcom/android/server/wm/WindowState;->getStack()Lcom/android/server/wm/TaskStack;
+Lcom/android/server/wm/WindowState;->transformSurfaceInsetsPosition(Landroid/graphics/Point;Landroid/graphics/Rect;)V
+Lcom/android/server/wm/WindowState;->prepareSurfaces()V
+Lcom/android/server/wm/WindowState;->applyDims(Lcom/android/server/wm/Dimmer;)V
+Lcom/android/server/wm/WindowStateAnimator;->prepareSurfaceLocked(Z)V
+Lcom/android/server/wm/RootWindowContainer;->performSurfacePlacementNoTrace(Z)V
+Lcom/android/server/wm/WindowState;->isVisibleLw()Z
+Lcom/android/server/wm/WindowSurfaceController;->hasSurface()Z
+Lcom/android/server/wm/WindowManagerService;->getDefaultDisplayContentLocked()Lcom/android/server/wm/DisplayContent;
+Lcom/android/server/wm/RootWindowContainer;->scheduleAnimation()V
+Lcom/android/server/wm/WindowContainer;->getWindow(Ljava/util/function/Predicate;)Lcom/android/server/wm/WindowState;
+Lcom/android/server/wm/WindowContainer;->needsZBoost()Z
+Lcom/android/server/wm/WindowState;->isOnScreen()Z
+Lcom/android/server/wm/utils/InsetUtils;->insetsBetweenFrames(Landroid/graphics/Rect;Landroid/graphics/Rect;Landroid/graphics/Rect;)V
+Lcom/android/server/wm/PolicyControl;->getWindowFlags(Lcom/android/server/wm/WindowState;Landroid/view/WindowManager$LayoutParams;)I
+Lcom/android/server/wm/WindowContainer;->getChildAt(I)Lcom/android/server/wm/WindowContainer;
+Lcom/android/server/wm/InsetsStateController;->onPostLayout()V
+Lcom/android/server/wm/WindowFrames;->setContentChanged(Z)V
+Lcom/android/server/wm/DisplayContent$NonAppWindowContainers;->prepareSurfaces()V
+Lcom/android/server/wm/DisplayContent;->getHomeStack()Lcom/android/server/wm/TaskStack;
+Lcom/android/server/wm/DisplayContent$TaskStackContainers;->getHomeStack()Lcom/android/server/wm/TaskStack;
+Lcom/android/server/wm/DisplayContent$NonAppWindowContainers;->getDimmer()Lcom/android/server/wm/Dimmer;
+Lcom/android/server/wm/RootActivityContainer;->getTopDisplayFocusedStack()Lcom/android/server/wm/ActivityStack;
+Lcom/android/server/wm/WindowState;->resetContentChanged()V
+Lcom/android/server/wm/WindowState;->isDragResizeChanged()Z
+Lcom/android/server/wm/WindowState;->computeDragResizing()Z
+Lcom/android/server/wm/WindowState;->isVisibleOrAdding()Z
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index b4ee0b1..8032e1b 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -887,7 +887,7 @@
mMetricsLogger.write(log);
if (intentSender != null) {
if (sDebug) Slog.d(TAG, "Starting intent sender on save()");
- startIntentSender(intentSender);
+ startIntentSenderAndFinishSession(intentSender);
}
// Nothing left to do...
@@ -1101,24 +1101,32 @@
// AutoFillUiCallback
@Override
- public void startIntentSender(IntentSender intentSender) {
+ public void startIntentSenderAndFinishSession(IntentSender intentSender) {
+ startIntentSender(intentSender, null);
+ }
+
+ // AutoFillUiCallback
+ @Override
+ public void startIntentSender(IntentSender intentSender, Intent intent) {
synchronized (mLock) {
if (mDestroyed) {
Slog.w(TAG, "Call to Session#startIntentSender() rejected - session: "
+ id + " destroyed");
return;
}
- removeSelfLocked();
+ if (intent == null) {
+ removeSelfLocked();
+ }
}
mHandler.sendMessage(obtainMessage(
Session::doStartIntentSender,
- this, intentSender));
+ this, intentSender, intent));
}
- private void doStartIntentSender(IntentSender intentSender) {
+ private void doStartIntentSender(IntentSender intentSender, Intent intent) {
try {
synchronized (mLock) {
- mClient.startIntentSender(intentSender, null);
+ mClient.startIntentSender(intentSender, intent);
}
} catch (RemoteException e) {
Slog.e(TAG, "Error launching auth intent", e);
@@ -1863,7 +1871,7 @@
mHandler.sendMessage(obtainMessage(Session::logSaveShown, this));
final IAutoFillManagerClient client = getClient();
- mPendingSaveUi = new PendingUi(mActivityToken, id, client);
+ mPendingSaveUi = new PendingUi(new Binder(), id, client);
final CharSequence serviceLabel;
final Drawable serviceIcon;
diff --git a/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java b/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
index fe86ab3..0b2e2bf 100644
--- a/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
+++ b/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
@@ -22,6 +22,7 @@
import android.annotation.Nullable;
import android.content.ComponentName;
import android.content.Context;
+import android.content.Intent;
import android.content.IntentSender;
import android.graphics.drawable.Drawable;
import android.metrics.LogMaker;
@@ -82,7 +83,8 @@
void requestShowFillUi(AutofillId id, int width, int height,
IAutofillWindowPresenter presenter);
void requestHideFillUi(AutofillId id);
- void startIntentSender(IntentSender intentSender);
+ void startIntentSenderAndFinishSession(IntentSender intentSender);
+ void startIntentSender(IntentSender intentSender, Intent intent);
void dispatchUnhandledKey(AutofillId id, KeyEvent keyEvent);
}
@@ -253,7 +255,7 @@
@Override
public void startIntentSender(IntentSender intentSender) {
if (mCallback != null) {
- mCallback.startIntentSender(intentSender);
+ mCallback.startIntentSenderAndFinishSession(intentSender);
}
}
@@ -338,6 +340,13 @@
}
mMetricsLogger.write(log);
}
+
+ @Override
+ public void startIntentSender(IntentSender intentSender, Intent intent) {
+ if (mCallback != null) {
+ mCallback.startIntentSender(intentSender, intent);
+ }
+ }
}, mUiModeMgr.isNightMode(), isUpdate, compatMode);
});
}
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 e2cdddb..8e20019 100644
--- a/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
+++ b/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
@@ -32,7 +32,6 @@
import android.metrics.LogMaker;
import android.os.Handler;
import android.os.IBinder;
-import android.os.RemoteException;
import android.service.autofill.BatchUpdates;
import android.service.autofill.CustomDescription;
import android.service.autofill.InternalOnClickAction;
@@ -83,6 +82,7 @@
void onSave();
void onCancel(IntentSender listener);
void onDestroy();
+ void startIntentSender(IntentSender intentSender, Intent intent);
}
/**
@@ -129,6 +129,15 @@
mDone = true;
mRealListener.onDestroy();
}
+
+ @Override
+ public void startIntentSender(IntentSender intentSender, Intent intent) {
+ if (sDebug) Slog.d(TAG, "OneTimeListener.startIntentSender(): " + mDone);
+ if (mDone) {
+ return;
+ }
+ mRealListener.startIntentSender(intentSender, intent);
+ }
}
private final Handler mHandler = UiThread.getHandler();
@@ -168,8 +177,8 @@
context = new ContextThemeWrapper(context, mThemeId) {
@Override
public void startActivity(Intent intent) {
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- super.startActivity(intent);
+ PendingIntent p = PendingIntent.getActivity(this, 0, intent, 0);
+ mListener.startIntentSender(p.getIntentSender(), intent);
}
};
final LayoutInflater inflater = LayoutInflater.from(context);
@@ -329,21 +338,13 @@
if (sVerbose) Slog.v(TAG, "Intercepting custom description intent");
final IBinder token = mPendingUi.getToken();
intent.putExtra(AutofillManager.EXTRA_RESTORE_SESSION_TOKEN, token);
- try {
- mPendingUi.client.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);
- return true;
- } catch (RemoteException e) {
- Slog.w(TAG, "error triggering pending intent: " + intent);
- log.setType(MetricsEvent.TYPE_FAILURE);
- mMetricsLogger.write(log);
- return false;
- }
+ 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);
+ return true;
};
try {
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index 814f6da..dc0bdb3 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -31,14 +31,11 @@
import android.app.job.JobParameters;
import android.app.job.JobScheduler;
import android.app.job.JobService;
-import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
-import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.os.Binder;
-import android.os.FileUtils;
import android.os.IBinder;
import android.os.ParcelFileDescriptor;
import android.os.Trace;
@@ -49,13 +46,10 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.DumpUtils;
-import com.android.server.SystemConfig;
import com.android.server.SystemService;
-import java.io.File;
import java.io.FileDescriptor;
import java.io.PrintWriter;
-import java.util.Collections;
import java.util.Set;
/**
@@ -74,64 +68,16 @@
@VisibleForTesting
static final String DUMP_RUNNING_USERS_MESSAGE = "Backup Manager is running for users:";
- // The published binder is a singleton Trampoline object that calls through to the proper code.
- // This indirection lets us turn down the heavy implementation object on the fly without
- // disturbing binders that have been cached elsewhere in the system.
- private static Trampoline sInstance;
-
- static Trampoline getInstance() {
- // Always constructed during system bring up, so no need to lazy-init.
- return sInstance;
- }
-
private final Context mContext;
private final Trampoline mTrampoline;
// Keeps track of all unlocked users registered with this service. Indexed by user id.
private final SparseArray<UserBackupManagerService> mServiceUsers = new SparseArray<>();
- private Set<ComponentName> mTransportWhitelist;
-
- private final BroadcastReceiver mUserRemovedReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- if (Intent.ACTION_USER_REMOVED.equals(intent.getAction())) {
- int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL);
- if (userId > 0) { // for only non system users
- onRemovedNonSystemUser(userId);
- }
- }
- }
- };
-
/** Instantiate a new instance of {@link BackupManagerService}. */
public BackupManagerService(Context context, Trampoline trampoline) {
mContext = checkNotNull(context);
mTrampoline = checkNotNull(trampoline);
-
- // Set up our transport options.
- SystemConfig systemConfig = SystemConfig.getInstance();
- mTransportWhitelist = systemConfig.getBackupTransportWhitelist();
- if (mTransportWhitelist == null) {
- mTransportWhitelist = Collections.emptySet();
- }
-
- mContext.registerReceiver(mUserRemovedReceiver,
- new IntentFilter(Intent.ACTION_USER_REMOVED));
- }
-
- /**
- * Remove backup state for non system {@code userId} when the user is removed from the device.
- * For non system users, backup state is stored in both the user's own dir and the system dir.
- * When the user is removed, the user's own dir gets removed by the OS. This method ensures that
- * the part of the user backup state which is in the system dir also gets removed.
- */
- private void onRemovedNonSystemUser(int userId) {
- Slog.i(TAG, "Removing state for non system user " + userId);
- File dir = UserBackupManagerFiles.getStateDirInSystemDir(userId);
- if (!FileUtils.deleteContentsAndDir(dir)) {
- Slog.w(TAG, "Failed to delete state dir for removed user: " + userId);
- }
}
/**
@@ -157,7 +103,7 @@
* UserBackupManagerService} and registering it with this service.
*/
@VisibleForTesting
- protected void startServiceForUser(int userId) {
+ protected void startServiceForUser(int userId, Set<ComponentName> transportWhitelist) {
if (mServiceUsers.get(userId) != null) {
Slog.i(TAG, "userId " + userId + " already started, so not starting again");
return;
@@ -165,7 +111,7 @@
UserBackupManagerService userBackupManagerService =
UserBackupManagerService.createAndInitializeService(
- userId, mContext, mTrampoline, mTransportWhitelist);
+ userId, mContext, mTrampoline, transportWhitelist);
startServiceForUser(userId, userBackupManagerService);
}
@@ -374,19 +320,6 @@
: userBackupManagerService.listAllTransportComponents();
}
- /** Report all system whitelisted transports. */
- @Nullable
- public String[] getTransportWhitelist() {
- // No permission check, intentionally.
- String[] whitelistedTransports = new String[mTransportWhitelist.size()];
- int i = 0;
- for (ComponentName component : mTransportWhitelist) {
- whitelistedTransports[i] = component.flattenToShortString();
- i++;
- }
- return whitelistedTransports;
- }
-
/**
* Update the attributes of the transport identified by {@code transportComponent}. If the
* specified transport has not been bound at least once (for registration), this call will be
@@ -895,22 +828,22 @@
@VisibleForTesting
Lifecycle(Context context, Trampoline trampoline) {
super(context);
- sInstance = trampoline;
+ Trampoline.sInstance = trampoline;
}
@Override
public void onStart() {
- publishService(Context.BACKUP_SERVICE, sInstance);
+ publishService(Context.BACKUP_SERVICE, Trampoline.sInstance);
}
@Override
public void onUnlockUser(int userId) {
- sInstance.onUnlockUser(userId);
+ Trampoline.sInstance.onUnlockUser(userId);
}
@Override
public void onStopUser(int userId) {
- sInstance.onStopUser(userId);
+ Trampoline.sInstance.onStopUser(userId);
}
@VisibleForTesting
diff --git a/services/backup/java/com/android/server/backup/FullBackupJob.java b/services/backup/java/com/android/server/backup/FullBackupJob.java
index 088e1f9..19a8543 100644
--- a/services/backup/java/com/android/server/backup/FullBackupJob.java
+++ b/services/backup/java/com/android/server/backup/FullBackupJob.java
@@ -91,7 +91,7 @@
mParamsForUser.put(userId, params);
}
- Trampoline service = BackupManagerService.getInstance();
+ Trampoline service = Trampoline.getInstance();
return service.beginFullBackup(userId, this);
}
@@ -105,7 +105,7 @@
}
}
- Trampoline service = BackupManagerService.getInstance();
+ Trampoline service = Trampoline.getInstance();
service.endFullBackup(userId);
return false;
diff --git a/services/backup/java/com/android/server/backup/KeyValueBackupJob.java b/services/backup/java/com/android/server/backup/KeyValueBackupJob.java
index ac43fc3..7b5dbd7 100644
--- a/services/backup/java/com/android/server/backup/KeyValueBackupJob.java
+++ b/services/backup/java/com/android/server/backup/KeyValueBackupJob.java
@@ -144,7 +144,7 @@
}
// Time to run a key/value backup!
- Trampoline service = BackupManagerService.getInstance();
+ Trampoline service = Trampoline.getInstance();
try {
service.backupNowForUser(userId);
} catch (RemoteException e) {}
diff --git a/services/backup/java/com/android/server/backup/Trampoline.java b/services/backup/java/com/android/server/backup/Trampoline.java
index 210a9ef..59d9c0e 100644
--- a/services/backup/java/com/android/server/backup/Trampoline.java
+++ b/services/backup/java/com/android/server/backup/Trampoline.java
@@ -16,8 +16,11 @@
package com.android.server.backup;
+import static com.android.internal.util.Preconditions.checkNotNull;
import static com.android.server.backup.BackupManagerService.TAG;
+import static java.util.Collections.emptySet;
+
import android.Manifest;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
@@ -29,10 +32,13 @@
import android.app.backup.IFullBackupRestoreObserver;
import android.app.backup.IRestoreSession;
import android.app.backup.ISelectBackupTransportCallback;
+import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
+import android.content.IntentFilter;
import android.os.Binder;
+import android.os.FileUtils;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
@@ -47,12 +53,14 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.DumpUtils;
+import com.android.server.SystemConfig;
import com.android.server.backup.utils.RandomAccessFileUtils;
import java.io.File;
import java.io.FileDescriptor;
import java.io.IOException;
import java.io.PrintWriter;
+import java.util.Set;
/**
* A proxy to the {@link BackupManagerService} implementation.
@@ -98,6 +106,12 @@
private static final String BACKUP_THREAD = "backup";
+ static Trampoline sInstance;
+
+ static Trampoline getInstance() {
+ return checkNotNull(sInstance);
+ }
+
private final Context mContext;
private final UserManager mUserManager;
@@ -111,6 +125,19 @@
@VisibleForTesting
protected volatile BackupManagerService mService;
private final Handler mHandler;
+ private final Set<ComponentName> mTransportWhitelist;
+
+ private final BroadcastReceiver mUserRemovedReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (Intent.ACTION_USER_REMOVED.equals(intent.getAction())) {
+ int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL);
+ if (userId > 0) { // for only non system users
+ mHandler.post(() -> onRemovedNonSystemUser(userId));
+ }
+ }
+ }
+ };
public Trampoline(Context context) {
mContext = context;
@@ -121,6 +148,11 @@
mHandler = new Handler(handlerThread.getLooper());
mUserManager = UserManager.get(context);
mService = new BackupManagerService(mContext, this);
+ Set<ComponentName> transportWhitelist =
+ SystemConfig.getInstance().getBackupTransportWhitelist();
+ mTransportWhitelist = (transportWhitelist == null) ? emptySet() : transportWhitelist;
+ mContext.registerReceiver(
+ mUserRemovedReceiver, new IntentFilter(Intent.ACTION_USER_REMOVED));
}
// TODO: Remove this when we implement DI by injecting in the construtor.
@@ -157,6 +189,20 @@
return UserBackupManagerFiles.getStateFileInSystemDir(BACKUP_ACTIVATED_FILENAME, userId);
}
+ /**
+ * Remove backup state for non system {@code userId} when the user is removed from the device.
+ * For non system users, backup state is stored in both the user's own dir and the system dir.
+ * When the user is removed, the user's own dir gets removed by the OS. This method ensures that
+ * the part of the user backup state which is in the system dir also gets removed.
+ */
+ private void onRemovedNonSystemUser(int userId) {
+ Slog.i(TAG, "Removing state for non system user " + userId);
+ File dir = UserBackupManagerFiles.getStateDirInSystemDir(userId);
+ if (!FileUtils.deleteContentsAndDir(dir)) {
+ Slog.w(TAG, "Failed to delete state dir for removed user: " + userId);
+ }
+ }
+
// TODO (b/124359804) move to util method in FileUtils
private void createFile(File file) throws IOException {
if (file.exists()) {
@@ -263,7 +309,7 @@
return;
}
Slog.i(TAG, "Starting service for user: " + userId);
- mService.startServiceForUser(userId);
+ mService.startServiceForUser(userId, mTransportWhitelist);
}
/**
@@ -611,7 +657,17 @@
@Override
public String[] getTransportWhitelist() {
int userId = binderGetCallingUserId();
- return (isUserReadyForBackup(userId)) ? mService.getTransportWhitelist() : null;
+ if (!isUserReadyForBackup(userId)) {
+ return null;
+ }
+ // No permission check, intentionally.
+ String[] whitelistedTransports = new String[mTransportWhitelist.size()];
+ int i = 0;
+ for (ComponentName component : mTransportWhitelist) {
+ whitelistedTransports[i] = component.flattenToShortString();
+ i++;
+ }
+ return whitelistedTransports;
}
@Override
diff --git a/services/backup/java/com/android/server/backup/UserBackupManagerService.java b/services/backup/java/com/android/server/backup/UserBackupManagerService.java
index ed4e596..d599aab 100644
--- a/services/backup/java/com/android/server/backup/UserBackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/UserBackupManagerService.java
@@ -166,6 +166,53 @@
/** System service that performs backup/restore operations. */
public class UserBackupManagerService {
+ /**
+ * Wrapper over {@link PowerManager.WakeLock} to prevent double-free exceptions on release()
+ * after quit().
+ */
+ public static class BackupWakeLock {
+ private final PowerManager.WakeLock mPowerManagerWakeLock;
+ private boolean mHasQuit = false;
+
+ public BackupWakeLock(PowerManager.WakeLock powerManagerWakeLock) {
+ mPowerManagerWakeLock = powerManagerWakeLock;
+ }
+
+ /** Acquires the {@link PowerManager.WakeLock} if hasn't been quit. */
+ public synchronized void acquire() {
+ if (mHasQuit) {
+ Slog.v(TAG, "Ignore wakelock acquire after quit: " + mPowerManagerWakeLock.getTag());
+ return;
+ }
+ mPowerManagerWakeLock.acquire();
+ }
+
+ /** Releases the {@link PowerManager.WakeLock} if hasn't been quit. */
+ public synchronized void release() {
+ if (mHasQuit) {
+ Slog.v(TAG, "Ignore wakelock release after quit: " + mPowerManagerWakeLock.getTag());
+ return;
+ }
+ mPowerManagerWakeLock.release();
+ }
+
+ /**
+ * Returns true if the {@link PowerManager.WakeLock} has been acquired but not yet released.
+ */
+ public synchronized boolean isHeld() {
+ return mPowerManagerWakeLock.isHeld();
+ }
+
+ /** Release the {@link PowerManager.WakeLock} till it isn't held. */
+ public synchronized void quit() {
+ while (mPowerManagerWakeLock.isHeld()) {
+ Slog.v(TAG, "Releasing wakelock: " + mPowerManagerWakeLock.getTag());
+ mPowerManagerWakeLock.release();
+ }
+ mHasQuit = true;
+ }
+ }
+
// Persistently track the need to do a full init.
private static final String INIT_SENTINEL_FILE_NAME = "_need_init_";
@@ -252,7 +299,6 @@
private final @UserIdInt int mUserId;
private final BackupAgentTimeoutParameters mAgentTimeoutParameters;
private final TransportManager mTransportManager;
- private final HandlerThread mUserBackupThread;
private final Context mContext;
private final PackageManager mPackageManager;
@@ -263,7 +309,7 @@
private final AlarmManager mAlarmManager;
private final IStorageManager mStorageManager;
private final BackupManagerConstants mConstants;
- private final PowerManager.WakeLock mWakelock;
+ private final BackupWakeLock mWakelock;
private final BackupHandler mBackupHandler;
private final IBackupManager mBackupManagerBinder;
@@ -487,8 +533,7 @@
mAgentTimeoutParameters.start();
checkNotNull(userBackupThread, "userBackupThread cannot be null");
- mUserBackupThread = userBackupThread;
- mBackupHandler = new BackupHandler(this, userBackupThread.getLooper());
+ mBackupHandler = new BackupHandler(this, userBackupThread);
// Set up our bookkeeping
final ContentResolver resolver = context.getContentResolver();
@@ -588,7 +633,10 @@
mBackupHandler.postDelayed(this::parseLeftoverJournals, INITIALIZATION_DELAY_MILLIS);
// Power management
- mWakelock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "*backup*-" + userId);
+ mWakelock = new BackupWakeLock(
+ mPowerManager.newWakeLock(
+ PowerManager.PARTIAL_WAKE_LOCK,
+ "*backup*-" + userId + "-" + userBackupThread.getThreadId()));
// Set up the various sorts of package tracking we do
mFullBackupScheduleFile = new File(mBaseStateDir, "fb-schedule");
@@ -608,7 +656,7 @@
mContext.unregisterReceiver(mRunBackupReceiver);
mContext.unregisterReceiver(mRunInitReceiver);
mContext.unregisterReceiver(mPackageTrackingReceiver);
- mUserBackupThread.quit();
+ mBackupHandler.stop();
}
public @UserIdInt int getUserId() {
@@ -668,7 +716,7 @@
mSetupComplete = setupComplete;
}
- public PowerManager.WakeLock getWakelock() {
+ public BackupWakeLock getWakelock() {
return mWakelock;
}
@@ -679,7 +727,7 @@
@VisibleForTesting
public void setWorkSource(@Nullable WorkSource workSource) {
// TODO: This is for testing, unfortunately WakeLock is final and WorkSource is not exposed
- mWakelock.setWorkSource(workSource);
+ mWakelock.mPowerManagerWakeLock.setWorkSource(workSource);
}
public Handler getBackupHandler() {
diff --git a/services/backup/java/com/android/server/backup/internal/BackupHandler.java b/services/backup/java/com/android/server/backup/internal/BackupHandler.java
index ba153bf..059b1b9 100644
--- a/services/backup/java/com/android/server/backup/internal/BackupHandler.java
+++ b/services/backup/java/com/android/server/backup/internal/BackupHandler.java
@@ -23,7 +23,7 @@
import android.app.backup.RestoreSet;
import android.content.Intent;
import android.os.Handler;
-import android.os.Looper;
+import android.os.HandlerThread;
import android.os.Message;
import android.os.RemoteException;
import android.os.UserHandle;
@@ -83,19 +83,47 @@
// backup task state machine tick
public static final int MSG_BACKUP_RESTORE_STEP = 20;
public static final int MSG_OP_COMPLETE = 21;
+ // Release the wakelock. This is used to ensure we don't hold it after
+ // a user is removed. This will also terminate the looper thread.
+ public static final int MSG_STOP = 22;
private final UserBackupManagerService backupManagerService;
private final BackupAgentTimeoutParameters mAgentTimeoutParameters;
- public BackupHandler(UserBackupManagerService backupManagerService, Looper looper) {
- super(looper);
+ private final HandlerThread mBackupThread;
+ private volatile boolean mIsStopping = false;
+
+ public BackupHandler(
+ UserBackupManagerService backupManagerService, HandlerThread backupThread) {
+ super(backupThread.getLooper());
+ mBackupThread = backupThread;
this.backupManagerService = backupManagerService;
mAgentTimeoutParameters = Preconditions.checkNotNull(
backupManagerService.getAgentTimeoutParameters(),
"Timeout parameters cannot be null");
}
+ /**
+ * Put the BackupHandler into a stopping state where the remaining messages on the queue will be
+ * silently dropped and the {@link WakeLock} held by the {@link UserBackupManagerService} will
+ * then be released.
+ */
+ public void stop() {
+ mIsStopping = true;
+ sendMessage(obtainMessage(BackupHandler.MSG_STOP));
+ }
+
public void handleMessage(Message msg) {
+ if (msg.what == MSG_STOP) {
+ Slog.v(TAG, "Stopping backup handler");
+ backupManagerService.getWakelock().quit();
+ mBackupThread.quitSafely();
+ }
+
+ if (mIsStopping) {
+ // If we're finishing all other types of messages should be ignored
+ return;
+ }
TransportManager transportManager = backupManagerService.getTransportManager();
switch (msg.what) {
diff --git a/services/backup/java/com/android/server/backup/internal/RunInitializeReceiver.java b/services/backup/java/com/android/server/backup/internal/RunInitializeReceiver.java
index 97711e3..96d61e5 100644
--- a/services/backup/java/com/android/server/backup/internal/RunInitializeReceiver.java
+++ b/services/backup/java/com/android/server/backup/internal/RunInitializeReceiver.java
@@ -23,7 +23,6 @@
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
-import android.os.PowerManager;
import android.util.Slog;
import com.android.server.backup.UserBackupManagerService;
@@ -57,7 +56,8 @@
mUserBackupManagerService.clearPendingInits();
- PowerManager.WakeLock wakelock = mUserBackupManagerService.getWakelock();
+ UserBackupManagerService.BackupWakeLock wakelock =
+ mUserBackupManagerService.getWakelock();
wakelock.acquire();
OnTaskFinishedListener listener = caller -> wakelock.release();
diff --git a/services/backup/java/com/android/server/backup/restore/ActiveRestoreSession.java b/services/backup/java/com/android/server/backup/restore/ActiveRestoreSession.java
index 10304c3..5a57cdc 100644
--- a/services/backup/java/com/android/server/backup/restore/ActiveRestoreSession.java
+++ b/services/backup/java/com/android/server/backup/restore/ActiveRestoreSession.java
@@ -34,7 +34,6 @@
import android.os.Binder;
import android.os.Handler;
import android.os.Message;
-import android.os.PowerManager;
import android.util.Slog;
import com.android.server.backup.TransportManager;
@@ -110,7 +109,7 @@
// comes in.
mBackupManagerService.getBackupHandler().removeMessages(MSG_RESTORE_SESSION_TIMEOUT);
- PowerManager.WakeLock wakelock = mBackupManagerService.getWakelock();
+ UserBackupManagerService.BackupWakeLock wakelock = mBackupManagerService.getWakelock();
wakelock.acquire();
// Prevent lambda from leaking 'this'
@@ -392,7 +391,7 @@
Handler backupHandler = mBackupManagerService.getBackupHandler();
backupHandler.removeMessages(MSG_RESTORE_SESSION_TIMEOUT);
- PowerManager.WakeLock wakelock = mBackupManagerService.getWakelock();
+ UserBackupManagerService.BackupWakeLock wakelock = mBackupManagerService.getWakelock();
wakelock.acquire();
if (MORE_DEBUG) {
Slog.d(TAG, callerLogString);
diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java
index d162441..fede487 100644
--- a/services/core/java/com/android/server/AlarmManagerService.java
+++ b/services/core/java/com/android/server/AlarmManagerService.java
@@ -2604,8 +2604,7 @@
mConstants.dumpProto(proto, AlarmManagerServiceDumpProto.SETTINGS);
if (mAppStateTracker != null) {
- mAppStateTracker.dumpProto(proto,
- AlarmManagerServiceDumpProto.FORCE_APP_STANDBY_TRACKER);
+ mAppStateTracker.dumpProto(proto, AlarmManagerServiceDumpProto.APP_STATE_TRACKER);
}
proto.write(AlarmManagerServiceDumpProto.IS_INTERACTIVE, mInteractive);
diff --git a/services/core/java/com/android/server/AppStateTracker.java b/services/core/java/com/android/server/AppStateTracker.java
index 3a7b5d6..2c67c50 100644
--- a/services/core/java/com/android/server/AppStateTracker.java
+++ b/services/core/java/com/android/server/AppStateTracker.java
@@ -56,8 +56,8 @@
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.Preconditions;
import com.android.internal.util.StatLogger;
-import com.android.server.ForceAppStandbyTrackerProto.ExemptedPackage;
-import com.android.server.ForceAppStandbyTrackerProto.RunAnyInBackgroundRestrictedPackages;
+import com.android.server.AppStateTrackerProto.ExemptedPackage;
+import com.android.server.AppStateTrackerProto.RunAnyInBackgroundRestrictedPackages;
import java.io.PrintWriter;
import java.util.Arrays;
@@ -1308,43 +1308,42 @@
synchronized (mLock) {
final long token = proto.start(fieldId);
- proto.write(ForceAppStandbyTrackerProto.FORCE_ALL_APPS_STANDBY, mForceAllAppsStandby);
- proto.write(ForceAppStandbyTrackerProto.IS_SMALL_BATTERY_DEVICE,
- isSmallBatteryDevice());
- proto.write(ForceAppStandbyTrackerProto.FORCE_ALL_APPS_STANDBY_FOR_SMALL_BATTERY,
+ proto.write(AppStateTrackerProto.FORCED_APP_STANDBY_FEATURE_ENABLED,
+ mForcedAppStandbyEnabled);
+ proto.write(AppStateTrackerProto.FORCE_ALL_APPS_STANDBY,
+ isForceAllAppsStandbyEnabled());
+ proto.write(AppStateTrackerProto.IS_SMALL_BATTERY_DEVICE, isSmallBatteryDevice());
+ proto.write(AppStateTrackerProto.FORCE_ALL_APPS_STANDBY_FOR_SMALL_BATTERY,
mForceAllAppStandbyForSmallBattery);
- proto.write(ForceAppStandbyTrackerProto.IS_PLUGGED_IN, mIsPluggedIn);
+ proto.write(AppStateTrackerProto.IS_PLUGGED_IN, mIsPluggedIn);
for (int i = 0; i < mActiveUids.size(); i++) {
if (mActiveUids.valueAt(i)) {
- proto.write(ForceAppStandbyTrackerProto.ACTIVE_UIDS,
- mActiveUids.keyAt(i));
+ proto.write(AppStateTrackerProto.ACTIVE_UIDS, mActiveUids.keyAt(i));
}
}
for (int i = 0; i < mForegroundUids.size(); i++) {
if (mForegroundUids.valueAt(i)) {
- proto.write(ForceAppStandbyTrackerProto.FOREGROUND_UIDS,
- mForegroundUids.keyAt(i));
+ proto.write(AppStateTrackerProto.FOREGROUND_UIDS, mForegroundUids.keyAt(i));
}
}
for (int appId : mPowerWhitelistedAllAppIds) {
- proto.write(ForceAppStandbyTrackerProto.POWER_SAVE_WHITELIST_APP_IDS, appId);
+ proto.write(AppStateTrackerProto.POWER_SAVE_WHITELIST_APP_IDS, appId);
}
for (int appId : mPowerWhitelistedUserAppIds) {
- proto.write(ForceAppStandbyTrackerProto.POWER_SAVE_USER_WHITELIST_APP_IDS, appId);
+ proto.write(AppStateTrackerProto.POWER_SAVE_USER_WHITELIST_APP_IDS, appId);
}
for (int appId : mTempWhitelistedAppIds) {
- proto.write(ForceAppStandbyTrackerProto.TEMP_POWER_SAVE_WHITELIST_APP_IDS, appId);
+ proto.write(AppStateTrackerProto.TEMP_POWER_SAVE_WHITELIST_APP_IDS, appId);
}
for (int i = 0; i < mExemptedPackages.size(); i++) {
for (int j = 0; j < mExemptedPackages.sizeAt(i); j++) {
- final long token2 = proto.start(
- ForceAppStandbyTrackerProto.EXEMPTED_PACKAGES);
+ final long token2 = proto.start(AppStateTrackerProto.EXEMPTED_PACKAGES);
proto.write(ExemptedPackage.USER_ID, mExemptedPackages.keyAt(i));
proto.write(ExemptedPackage.PACKAGE_NAME, mExemptedPackages.valueAt(i, j));
@@ -1355,14 +1354,14 @@
for (Pair<Integer, String> uidAndPackage : mRunAnyRestrictedPackages) {
final long token2 = proto.start(
- ForceAppStandbyTrackerProto.RUN_ANY_IN_BACKGROUND_RESTRICTED_PACKAGES);
+ AppStateTrackerProto.RUN_ANY_IN_BACKGROUND_RESTRICTED_PACKAGES);
proto.write(RunAnyInBackgroundRestrictedPackages.UID, uidAndPackage.first);
proto.write(RunAnyInBackgroundRestrictedPackages.PACKAGE_NAME,
uidAndPackage.second);
proto.end(token2);
}
- mStatLogger.dumpProto(proto, ForceAppStandbyTrackerProto.STATS);
+ mStatLogger.dumpProto(proto, AppStateTrackerProto.STATS);
proto.end(token);
}
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 293ab02..e67ccc4 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -150,7 +150,6 @@
import android.util.Pair;
import android.util.Slog;
import android.util.SparseArray;
-import android.util.SparseBooleanArray;
import android.util.SparseIntArray;
import android.util.Xml;
@@ -168,7 +167,6 @@
import com.android.internal.util.DumpUtils;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.MessageUtils;
-import com.android.internal.util.WakeupMessage;
import com.android.internal.util.XmlUtils;
import com.android.server.am.BatteryStatsService;
import com.android.server.connectivity.AutodestructReference;
@@ -305,7 +303,8 @@
/** Flag indicating if background data is restricted. */
private boolean mRestrictBackground;
- final private Context mContext;
+ private final Context mContext;
+ private final Dependencies mDeps;
// 0 is full bad, 100 is full good
private int mDefaultInetConditionPublished = 0;
@@ -586,11 +585,6 @@
private NetworkNotificationManager mNotifier;
private LingerMonitor mLingerMonitor;
- // sequence number for Networks; keep in sync with system/netd/NetworkController.cpp
- private static final int MIN_NET_ID = 100; // some reserved marks
- private static final int MAX_NET_ID = 65535 - 0x0400; // Top 1024 bits reserved by IpSecService
- private int mNextNetId = MIN_NET_ID;
-
// sequence number of NetworkRequests
private int mNextNetworkRequestId = 1;
@@ -834,19 +828,113 @@
}
};
+ /**
+ * Dependencies of ConnectivityService, for injection in tests.
+ */
+ @VisibleForTesting
+ public static class Dependencies {
+ /**
+ * Get system properties to use in ConnectivityService.
+ */
+ public MockableSystemProperties getSystemProperties() {
+ return new MockableSystemProperties();
+ }
+
+ /**
+ * Create a HandlerThread to use in ConnectivityService.
+ */
+ public HandlerThread makeHandlerThread() {
+ return new HandlerThread("ConnectivityServiceThread");
+ }
+
+ /**
+ * Get a reference to the NetworkStackClient.
+ */
+ public NetworkStackClient getNetworkStack() {
+ return NetworkStackClient.getInstance();
+ }
+
+ /**
+ * @see Tethering
+ */
+ public Tethering makeTethering(@NonNull Context context,
+ @NonNull INetworkManagementService nms,
+ @NonNull INetworkStatsService statsService,
+ @NonNull INetworkPolicyManager policyManager,
+ @NonNull TetheringDependencies tetheringDeps) {
+ return new Tethering(context, nms, statsService, policyManager,
+ IoThread.get().getLooper(), getSystemProperties(), tetheringDeps);
+ }
+
+ /**
+ * @see ProxyTracker
+ */
+ public ProxyTracker makeProxyTracker(@NonNull Context context,
+ @NonNull Handler connServiceHandler) {
+ return new ProxyTracker(context, connServiceHandler, EVENT_PROXY_HAS_CHANGED);
+ }
+
+ /**
+ * @see NetIdManager
+ */
+ public NetIdManager makeNetIdManager() {
+ return new NetIdManager();
+ }
+
+ /**
+ * @see NetworkUtils#queryUserAccess(int, int)
+ */
+ public boolean queryUserAccess(int uid, int netId) {
+ return NetworkUtils.queryUserAccess(uid, netId);
+ }
+
+ /**
+ * @see MultinetworkPolicyTracker
+ */
+ public MultinetworkPolicyTracker makeMultinetworkPolicyTracker(
+ @NonNull Context c, @NonNull Handler h, @NonNull Runnable r) {
+ return new MultinetworkPolicyTracker(c, h, r);
+ }
+
+ /**
+ * @see ServiceManager#checkService(String)
+ */
+ public boolean hasService(@NonNull String name) {
+ return ServiceManager.checkService(name) != null;
+ }
+
+ /**
+ * @see IpConnectivityMetrics.Logger
+ */
+ public IpConnectivityMetrics.Logger getMetricsLogger() {
+ return checkNotNull(LocalServices.getService(IpConnectivityMetrics.Logger.class),
+ "no IpConnectivityMetrics service");
+ }
+
+ /**
+ * @see IpConnectivityMetrics
+ */
+ public IIpConnectivityMetrics getIpConnectivityMetrics() {
+ return IIpConnectivityMetrics.Stub.asInterface(
+ ServiceManager.getService(IpConnectivityLog.SERVICE_NAME));
+ }
+ }
+
public ConnectivityService(Context context, INetworkManagementService netManager,
INetworkStatsService statsService, INetworkPolicyManager policyManager) {
- this(context, netManager, statsService, policyManager,
- getDnsResolver(), new IpConnectivityLog(), NetdService.getInstance());
+ this(context, netManager, statsService, policyManager, getDnsResolver(),
+ new IpConnectivityLog(), NetdService.getInstance(), new Dependencies());
}
@VisibleForTesting
protected ConnectivityService(Context context, INetworkManagementService netManager,
INetworkStatsService statsService, INetworkPolicyManager policyManager,
- IDnsResolver dnsresolver, IpConnectivityLog logger, INetd netd) {
+ IDnsResolver dnsresolver, IpConnectivityLog logger, INetd netd, Dependencies deps) {
if (DBG) log("ConnectivityService starting up");
- mSystemProperties = getSystemProperties();
+ mDeps = checkNotNull(deps, "missing Dependencies");
+ mSystemProperties = mDeps.getSystemProperties();
+ mNetIdManager = mDeps.makeNetIdManager();
mMetricsLog = logger;
mDefaultRequest = createDefaultInternetRequestForTransport(-1, NetworkRequest.Type.REQUEST);
@@ -863,7 +951,7 @@
mDefaultWifiRequest = createDefaultInternetRequestForTransport(
NetworkCapabilities.TRANSPORT_WIFI, NetworkRequest.Type.BACKGROUND_REQUEST);
- mHandlerThread = new HandlerThread("ConnectivityServiceThread");
+ mHandlerThread = mDeps.makeHandlerThread();
mHandlerThread.start();
mHandler = new InternalHandler(mHandlerThread.getLooper());
mTrackerHandler = new NetworkStateTrackerHandler(mHandlerThread.getLooper());
@@ -881,7 +969,7 @@
LocalServices.getService(NetworkPolicyManagerInternal.class),
"missing NetworkPolicyManagerInternal");
mDnsResolver = checkNotNull(dnsresolver, "missing IDnsResolver");
- mProxyTracker = makeProxyTracker();
+ mProxyTracker = mDeps.makeProxyTracker(mContext, mHandler);
mNetd = netd;
mKeyStore = KeyStore.getInstance();
@@ -949,7 +1037,7 @@
// Do the same for Ethernet, since it's often not specified in the configs, although many
// devices can use it via USB host adapters.
- if (mNetConfigs[TYPE_ETHERNET] == null && hasService(Context.ETHERNET_SERVICE)) {
+ if (mNetConfigs[TYPE_ETHERNET] == null && mDeps.hasService(Context.ETHERNET_SERVICE)) {
mLegacyTypeTracker.addSupportedType(TYPE_ETHERNET);
mNetworksDefined++;
}
@@ -969,7 +1057,8 @@
mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
- mTethering = makeTethering();
+ mTethering = deps.makeTethering(mContext, mNMS, mStatsService, mPolicyManager,
+ makeTetheringDependencies());
mPermissionMonitor = new PermissionMonitor(mContext, mNetd);
@@ -1028,7 +1117,7 @@
LingerMonitor.DEFAULT_NOTIFICATION_RATE_LIMIT_MILLIS);
mLingerMonitor = new LingerMonitor(mContext, mNotifier, dailyLimit, rateLimit);
- mMultinetworkPolicyTracker = createMultinetworkPolicyTracker(
+ mMultinetworkPolicyTracker = mDeps.makeMultinetworkPolicyTracker(
mContext, mHandler, () -> rematchForAvoidBadWifiUpdate());
mMultinetworkPolicyTracker.start();
@@ -1038,10 +1127,8 @@
registerPrivateDnsSettingsCallbacks();
}
- @VisibleForTesting
- protected Tethering makeTethering() {
- // TODO: Move other elements into @Overridden getters.
- final TetheringDependencies deps = new TetheringDependencies() {
+ private TetheringDependencies makeTetheringDependencies() {
+ return new TetheringDependencies() {
@Override
public boolean isTetheringSupported() {
return ConnectivityService.this.isTetheringSupported();
@@ -1051,14 +1138,6 @@
return mDefaultRequest;
}
};
- return new Tethering(mContext, mNMS, mStatsService, mPolicyManager,
- IoThread.get().getLooper(), new MockableSystemProperties(),
- deps);
- }
-
- @VisibleForTesting
- protected ProxyTracker makeProxyTracker() {
- return new ProxyTracker(mContext, mHandler, EVENT_PROXY_HAS_CHANGED);
}
private static NetworkCapabilities createDefaultNetworkCapabilitiesForUid(int uid) {
@@ -1150,22 +1229,6 @@
return mNextNetworkRequestId++;
}
- @VisibleForTesting
- protected int reserveNetId() {
- synchronized (mNetworkForNetId) {
- for (int i = MIN_NET_ID; i <= MAX_NET_ID; i++) {
- int netId = mNextNetId;
- if (++mNextNetId > MAX_NET_ID) mNextNetId = MIN_NET_ID;
- // Make sure NetID unused. http://b/16815182
- if (!mNetIdInUse.get(netId)) {
- mNetIdInUse.put(netId, true);
- return netId;
- }
- }
- }
- throw new IllegalStateException("No free netIds");
- }
-
private NetworkState getFilteredNetworkState(int networkType, int uid) {
if (mLegacyTypeTracker.isTypeSupported(networkType)) {
final NetworkAgentInfo nai = mLegacyTypeTracker.getNetworkForType(networkType);
@@ -1797,11 +1860,8 @@
}
};
- @VisibleForTesting
- protected void registerNetdEventCallback() {
- final IIpConnectivityMetrics ipConnectivityMetrics =
- IIpConnectivityMetrics.Stub.asInterface(
- ServiceManager.getService(IpConnectivityLog.SERVICE_NAME));
+ private void registerNetdEventCallback() {
+ final IIpConnectivityMetrics ipConnectivityMetrics = mDeps.getIpConnectivityMetrics();
if (ipConnectivityMetrics == null) {
Slog.wtf(TAG, "Missing IIpConnectivityMetrics");
return;
@@ -2237,12 +2297,6 @@
protected static final String DEFAULT_TCP_BUFFER_SIZES = "4096,87380,110208,4096,16384,110208";
private static final String DEFAULT_TCP_RWND_KEY = "net.tcp.default_init_rwnd";
- // Overridden for testing purposes to avoid writing to SystemProperties.
- @VisibleForTesting
- protected MockableSystemProperties getSystemProperties() {
- return new MockableSystemProperties();
- }
-
private void updateTcpBufferSizes(String tcpBufferSizes) {
String[] values = null;
if (tcpBufferSizes != null) {
@@ -2632,8 +2686,9 @@
}
if (valid != nai.lastValidated) {
if (wasDefault) {
- metricsLogger().defaultNetworkMetrics().logDefaultNetworkValidity(
- SystemClock.elapsedRealtime(), valid);
+ mDeps.getMetricsLogger()
+ .defaultNetworkMetrics().logDefaultNetworkValidity(
+ SystemClock.elapsedRealtime(), valid);
}
final int oldScore = nai.getCurrentScore();
nai.lastValidated = valid;
@@ -2968,8 +3023,8 @@
final boolean wasDefault = isDefaultNetwork(nai);
synchronized (mNetworkForNetId) {
mNetworkForNetId.remove(nai.network.netId);
- mNetIdInUse.delete(nai.network.netId);
}
+ mNetIdManager.releaseNetId(nai.network.netId);
// Just in case.
mLegacyTypeTracker.remove(nai, wasDefault);
}
@@ -3016,7 +3071,7 @@
// if there is a fallback. Taken together, the two form a X -> 0, 0 -> Y sequence
// whose timestamps tell how long it takes to recover a default network.
long now = SystemClock.elapsedRealtime();
- metricsLogger().defaultNetworkMetrics().logDefaultNetworkEvent(now, null, nai);
+ mDeps.getMetricsLogger().defaultNetworkMetrics().logDefaultNetworkEvent(now, null, nai);
}
notifyIfacesChangedForNetworkStats();
// TODO - we shouldn't send CALLBACK_LOST to requests that can be satisfied
@@ -3070,9 +3125,7 @@
destroyNativeNetwork(nai);
mDnsManager.removeNetwork(nai.network);
}
- synchronized (mNetworkForNetId) {
- mNetIdInUse.delete(nai.network.netId);
- }
+ mNetIdManager.releaseNetId(nai.network.netId);
}
private boolean createNativeNetwork(@NonNull NetworkAgentInfo networkAgent) {
@@ -4156,7 +4209,7 @@
return null;
}
return getLinkPropertiesProxyInfo(activeNetwork);
- } else if (queryUserAccess(Binder.getCallingUid(), network.netId)) {
+ } else if (mDeps.queryUserAccess(Binder.getCallingUid(), network.netId)) {
// Don't call getLinkProperties() as it requires ACCESS_NETWORK_STATE permission, which
// caller may not have.
return getLinkPropertiesProxyInfo(network);
@@ -4165,10 +4218,6 @@
return null;
}
- @VisibleForTesting
- protected boolean queryUserAccess(int uid, int netId) {
- return NetworkUtils.queryUserAccess(uid, netId);
- }
private ProxyInfo getLinkPropertiesProxyInfo(Network network) {
final NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network);
@@ -4761,7 +4810,7 @@
final long ident = Binder.clearCallingIdentity();
try {
// Concatenate the range of types onto the range of NetIDs.
- int id = MAX_NET_ID + 1 + (networkType - ConnectivityManager.TYPE_NONE);
+ int id = NetIdManager.MAX_NET_ID + 1 + (networkType - ConnectivityManager.TYPE_NONE);
mNotifier.setProvNotificationVisible(visible, id, action);
} finally {
Binder.restoreCallingIdentity(ident);
@@ -5372,10 +5421,9 @@
@GuardedBy("mNetworkForNetId")
private final SparseArray<NetworkAgentInfo> mNetworkForNetId = new SparseArray<>();
// NOTE: Accessed on multiple threads, synchronized with mNetworkForNetId.
- // An entry is first added to mNetIdInUse, prior to mNetworkForNetId, so
+ // An entry is first reserved with NetIdManager, prior to being added to mNetworkForNetId, so
// there may not be a strict 1:1 correlation between the two.
- @GuardedBy("mNetworkForNetId")
- private final SparseBooleanArray mNetIdInUse = new SparseBooleanArray();
+ private final NetIdManager mNetIdManager;
// NetworkAgentInfo keyed off its connecting messenger
// TODO - eval if we can reduce the number of lists/hashmaps/sparsearrays
@@ -5477,9 +5525,9 @@
// satisfies mDefaultRequest.
final NetworkCapabilities nc = new NetworkCapabilities(networkCapabilities);
final NetworkAgentInfo nai = new NetworkAgentInfo(messenger, new AsyncChannel(),
- new Network(reserveNetId()), new NetworkInfo(networkInfo), lp, nc, currentScore,
- mContext, mTrackerHandler, new NetworkMisc(networkMisc), this, mNetd, mDnsResolver,
- mNMS, factorySerialNumber);
+ new Network(mNetIdManager.reserveNetId()), new NetworkInfo(networkInfo), lp, nc,
+ currentScore, mContext, mTrackerHandler, new NetworkMisc(networkMisc), this, mNetd,
+ mDnsResolver, mNMS, factorySerialNumber);
// Make sure the network capabilities reflect what the agent info says.
nai.setNetworkCapabilities(mixInCapabilities(nai, nc));
final String extraInfo = networkInfo.getExtraInfo();
@@ -5488,7 +5536,7 @@
if (DBG) log("registerNetworkAgent " + nai);
final long token = Binder.clearCallingIdentity();
try {
- getNetworkStack().makeNetworkMonitor(
+ mDeps.getNetworkStack().makeNetworkMonitor(
nai.network, name, new NetworkMonitorCallbacks(nai));
} finally {
Binder.restoreCallingIdentity(token);
@@ -5500,11 +5548,6 @@
return nai.network.netId;
}
- @VisibleForTesting
- protected NetworkStackClient getNetworkStack() {
- return NetworkStackClient.getInstance();
- }
-
private void handleRegisterNetworkAgent(NetworkAgentInfo nai, INetworkMonitor networkMonitor) {
nai.onNetworkMonitorCreated(networkMonitor);
if (VDBG) log("Got NetworkAgent Messenger");
@@ -6313,7 +6356,7 @@
// Notify system services that this network is up.
makeDefault(newNetwork);
// Log 0 -> X and Y -> X default network transitions, where X is the new default.
- metricsLogger().defaultNetworkMetrics().logDefaultNetworkEvent(
+ mDeps.getMetricsLogger().defaultNetworkMetrics().logDefaultNetworkEvent(
now, newNetwork, oldDefaultNetwork);
// Have a new default network, release the transition wakelock in
scheduleReleaseNetworkTransitionWakelock();
@@ -6990,27 +7033,6 @@
return nwm.getWatchlistConfigHash();
}
- @VisibleForTesting
- MultinetworkPolicyTracker createMultinetworkPolicyTracker(Context c, Handler h, Runnable r) {
- return new MultinetworkPolicyTracker(c, h, r);
- }
-
- @VisibleForTesting
- public WakeupMessage makeWakeupMessage(Context c, Handler h, String s, int cmd, Object obj) {
- return new WakeupMessage(c, h, s, cmd, 0, 0, obj);
- }
-
- @VisibleForTesting
- public boolean hasService(String name) {
- return ServiceManager.checkService(name) != null;
- }
-
- @VisibleForTesting
- protected IpConnectivityMetrics.Logger metricsLogger() {
- return checkNotNull(LocalServices.getService(IpConnectivityMetrics.Logger.class),
- "no IpConnectivityMetrics service");
- }
-
private void logNetworkEvent(NetworkAgentInfo nai, int evtype) {
int[] transports = nai.networkCapabilities.getTransportTypes();
mMetricsLog.log(nai.network.netId, transports, new NetworkEvent(evtype));
diff --git a/services/core/java/com/android/server/DynamicSystemService.java b/services/core/java/com/android/server/DynamicSystemService.java
index 173d5b0..e531412 100644
--- a/services/core/java/com/android/server/DynamicSystemService.java
+++ b/services/core/java/com/android/server/DynamicSystemService.java
@@ -181,18 +181,16 @@
@Override
public boolean remove() throws RemoteException {
- return getGsiService().removeGsiInstall();
+ return getGsiService().removeGsi();
}
@Override
- public boolean setEnable(boolean enable) throws RemoteException {
+ public boolean setEnable(boolean enable, boolean oneShot) throws RemoteException {
IGsiService gsiService = getGsiService();
if (enable) {
- final int status = gsiService.getGsiBootStatus();
- final boolean singleBoot = (status == IGsiService.BOOT_STATUS_SINGLE_BOOT);
- return gsiService.setGsiBootable(singleBoot) == 0;
+ return gsiService.enableGsi(oneShot) == 0;
} else {
- return gsiService.disableGsiInstall();
+ return gsiService.disableGsi();
}
}
@@ -200,9 +198,4 @@
public boolean write(byte[] buf) throws RemoteException {
return getGsiService().commitGsiChunkFromMemory(buf);
}
-
- @Override
- public boolean commit() throws RemoteException {
- return getGsiService().setGsiBootable(true) == 0;
- }
}
diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java
index fe22dcd..a629b3f 100644
--- a/services/core/java/com/android/server/IpSecService.java
+++ b/services/core/java/com/android/server/IpSecService.java
@@ -750,10 +750,10 @@
}
}
- // These values have been reserved in ConnectivityService
+ // These values have been reserved in NetIdManager
@VisibleForTesting static final int TUN_INTF_NETID_START = 0xFC00;
- @VisibleForTesting static final int TUN_INTF_NETID_RANGE = 0x0400;
+ public static final int TUN_INTF_NETID_RANGE = 0x0400;
private final SparseBooleanArray mTunnelNetIds = new SparseBooleanArray();
private int mNextTunnelNetIdIndex = 0;
diff --git a/services/core/java/com/android/server/NetIdManager.java b/services/core/java/com/android/server/NetIdManager.java
new file mode 100644
index 0000000..11533be
--- /dev/null
+++ b/services/core/java/com/android/server/NetIdManager.java
@@ -0,0 +1,76 @@
+/*
+ * 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;
+
+import android.annotation.NonNull;
+import android.util.SparseBooleanArray;
+
+import com.android.internal.annotations.GuardedBy;
+
+/**
+ * Class used to reserve and release net IDs.
+ *
+ * <p>Instances of this class are thread-safe.
+ */
+public class NetIdManager {
+ // Sequence number for Networks; keep in sync with system/netd/NetworkController.cpp
+ public static final int MIN_NET_ID = 100; // some reserved marks
+ // Top IDs reserved by IpSecService
+ public static final int MAX_NET_ID = 65535 - IpSecService.TUN_INTF_NETID_RANGE;
+
+ @GuardedBy("mNetIdInUse")
+ private final SparseBooleanArray mNetIdInUse = new SparseBooleanArray();
+
+ @GuardedBy("mNetIdInUse")
+ private int mLastNetId = MIN_NET_ID - 1;
+
+ /**
+ * Get the first netId that follows the provided lastId and is available.
+ */
+ private static int getNextAvailableNetIdLocked(
+ int lastId, @NonNull SparseBooleanArray netIdInUse) {
+ int netId = lastId;
+ for (int i = MIN_NET_ID; i <= MAX_NET_ID; i++) {
+ netId = netId < MAX_NET_ID ? netId + 1 : MIN_NET_ID;
+ if (!netIdInUse.get(netId)) {
+ return netId;
+ }
+ }
+ throw new IllegalStateException("No free netIds");
+ }
+
+ /**
+ * Reserve a new ID for a network.
+ */
+ public int reserveNetId() {
+ synchronized (mNetIdInUse) {
+ mLastNetId = getNextAvailableNetIdLocked(mLastNetId, mNetIdInUse);
+ // Make sure NetID unused. http://b/16815182
+ mNetIdInUse.put(mLastNetId, true);
+ return mLastNetId;
+ }
+ }
+
+ /**
+ * Clear a previously reserved ID for a network.
+ */
+ public void releaseNetId(int id) {
+ synchronized (mNetIdInUse) {
+ mNetIdInUse.delete(id);
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/PinnerService.java b/services/core/java/com/android/server/PinnerService.java
index 80facbb..49ef164 100644
--- a/services/core/java/com/android/server/PinnerService.java
+++ b/services/core/java/com/android/server/PinnerService.java
@@ -25,6 +25,7 @@
import android.app.ActivityManagerInternal;
import android.app.IActivityManager;
import android.app.IUidObserver;
+import android.app.SearchManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -94,6 +95,7 @@
private static final int KEY_CAMERA = 0;
private static final int KEY_HOME = 1;
+ private static final int KEY_ASSISTANT = 2;
// Pin the camera application.
private static boolean PROP_PIN_CAMERA = SystemProperties.getBoolean(
@@ -107,8 +109,9 @@
private static final int MAX_CAMERA_PIN_SIZE = 80 * (1 << 20); // 80MB max for camera app.
private static final int MAX_HOME_PIN_SIZE = 6 * (1 << 20); // 6MB max for home app.
+ private static final int MAX_ASSISTANT_PIN_SIZE = 60 * (1 << 20); // 60MB max for assistant app.
- @IntDef({KEY_CAMERA, KEY_HOME})
+ @IntDef({KEY_CAMERA, KEY_HOME, KEY_ASSISTANT})
@Retention(RetentionPolicy.SOURCE)
public @interface AppKey {}
@@ -117,6 +120,7 @@
private final ActivityManagerInternal mAmInternal;
private final IActivityManager mAm;
private final UserManager mUserManager;
+ private SearchManager mSearchManager;
/** The list of the statically pinned files. */
@GuardedBy("this")
@@ -167,6 +171,8 @@
com.android.internal.R.bool.config_pinnerCameraApp);
boolean shouldPinHome = context.getResources().getBoolean(
com.android.internal.R.bool.config_pinnerHomeApp);
+ boolean shouldPinAssistant = context.getResources().getBoolean(
+ com.android.internal.R.bool.config_pinnerAssistantApp);
if (shouldPinCamera) {
if (PROP_PIN_CAMERA) {
mPinKeys.add(KEY_CAMERA);
@@ -177,6 +183,9 @@
if (shouldPinHome) {
mPinKeys.add(KEY_HOME);
}
+ if (shouldPinAssistant) {
+ mPinKeys.add(KEY_ASSISTANT);
+ }
mPinnerHandler = new PinnerHandler(BackgroundThread.get().getLooper());
mAtmInternal = LocalServices.getService(ActivityTaskManagerInternal.class);
@@ -207,6 +216,15 @@
sendPinAppsMessage(UserHandle.USER_SYSTEM);
}
+ @Override
+ public void onBootPhase(int phase) {
+ // SearchManagerService is started after PinnerService, wait for PHASE_SYSTEM_SERVICES_READY
+ if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {
+ mSearchManager = (SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE);
+ sendPinAppsMessage(UserHandle.USER_SYSTEM);
+ }
+ }
+
/**
* Repin apps on user switch.
* <p>
@@ -408,6 +426,14 @@
return getApplicationInfoForIntent(intent, userHandle, false);
}
+ private ApplicationInfo getAssistantInfo(int userHandle) {
+ if (mSearchManager != null) {
+ Intent intent = mSearchManager.getAssistIntent(false);
+ return getApplicationInfoForIntent(intent, userHandle, true);
+ }
+ return null;
+ }
+
private ApplicationInfo getApplicationInfoForIntent(Intent intent, int userHandle,
boolean defaultToSystemApp) {
if (intent == null) {
@@ -520,6 +546,8 @@
return getCameraInfo(userHandle);
case KEY_HOME:
return getHomeInfo(userHandle);
+ case KEY_ASSISTANT:
+ return getAssistantInfo(userHandle);
default:
return null;
}
@@ -534,6 +562,8 @@
return "Camera";
case KEY_HOME:
return "Home";
+ case KEY_ASSISTANT:
+ return "Assistant";
default:
return null;
}
@@ -548,6 +578,8 @@
return MAX_CAMERA_PIN_SIZE;
case KEY_HOME:
return MAX_HOME_PIN_SIZE;
+ case KEY_ASSISTANT:
+ return MAX_ASSISTANT_PIN_SIZE;
default:
return 0;
}
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index ddde7fe..4fab7c1 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -1557,10 +1557,11 @@
}
private void start() {
- connect();
+ connectStoraged();
+ connectVold();
}
- private void connect() {
+ private void connectStoraged() {
IBinder binder = ServiceManager.getService("storaged");
if (binder != null) {
try {
@@ -1569,7 +1570,7 @@
public void binderDied() {
Slog.w(TAG, "storaged died; reconnecting");
mStoraged = null;
- connect();
+ connectStoraged();
}
}, 0);
} catch (RemoteException e) {
@@ -1583,7 +1584,17 @@
Slog.w(TAG, "storaged not found; trying again");
}
- binder = ServiceManager.getService("vold");
+ if (mStoraged == null) {
+ BackgroundThread.getHandler().postDelayed(() -> {
+ connectStoraged();
+ }, DateUtils.SECOND_IN_MILLIS);
+ } else {
+ onDaemonConnected();
+ }
+ }
+
+ private void connectVold() {
+ IBinder binder = ServiceManager.getService("vold");
if (binder != null) {
try {
binder.linkToDeath(new DeathRecipient() {
@@ -1591,7 +1602,7 @@
public void binderDied() {
Slog.w(TAG, "vold died; reconnecting");
mVold = null;
- connect();
+ connectVold();
}
}, 0);
} catch (RemoteException e) {
@@ -1611,9 +1622,9 @@
Slog.w(TAG, "vold not found; trying again");
}
- if (mStoraged == null || mVold == null) {
+ if (mVold == null) {
BackgroundThread.getHandler().postDelayed(() -> {
- connect();
+ connectVold();
}, DateUtils.SECOND_IN_MILLIS);
} else {
onDaemonConnected();
diff --git a/services/core/java/com/android/server/accounts/AccountManagerServiceShellCommand.java b/services/core/java/com/android/server/accounts/AccountManagerServiceShellCommand.java
index 9e5f722..9bf0bd3 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerServiceShellCommand.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerServiceShellCommand.java
@@ -17,6 +17,7 @@
package com.android.server.accounts;
import android.annotation.NonNull;
+import android.app.ActivityManager;
import android.os.ShellCommand;
import android.os.UserHandle;
@@ -83,7 +84,7 @@
return null;
}
}
- return UserHandle.USER_SYSTEM;
+ return ActivityManager.getCurrentUser();
}
@Override
@@ -92,9 +93,11 @@
pw.println("Account manager service commands:");
pw.println(" help");
pw.println(" Print this help text.");
- pw.println(" set-bind-instant-service-allowed [--user <USER_ID>] true|false ");
+ pw.println(" set-bind-instant-service-allowed "
+ + "[--user <USER_ID> (current user if not specified)] true|false ");
pw.println(" Set whether binding to services provided by instant apps is allowed.");
- pw.println(" get-bind-instant-service-allowed [--user <USER_ID>]");
+ pw.println(" get-bind-instant-service-allowed "
+ + "[--user <USER_ID> (current user if not specified)]");
pw.println(" Get whether binding to services provided by instant apps is allowed.");
}
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index f731a6d..ede573a 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -2419,7 +2419,7 @@
// handlers to other threads. So take care to be explicit about the looper.
public ActivityManagerService(Context systemContext, ActivityTaskManagerService atm) {
LockGuard.installLock(this, LockGuard.INDEX_ACTIVITY);
- mInjector = new Injector();
+ mInjector = new Injector(systemContext);
mContext = systemContext;
mFactoryTest = FactoryTest.getMode();
@@ -5213,6 +5213,10 @@
}
}
+ // Let the ART runtime in zygote and system_server know that the boot completed.
+ ZYGOTE_PROCESS.bootCompleted();
+ VMRuntime.bootCompleted();
+
IntentFilter pkgFilter = new IntentFilter();
pkgFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
pkgFilter.addDataScheme("package");
@@ -12105,39 +12109,44 @@
final String shortLabel;
final long pss;
final long swapPss;
+ final long mRss;
final int id;
final boolean hasActivities;
ArrayList<MemItem> subitems;
- public MemItem(String _label, String _shortLabel, long _pss, long _swapPss, int _id,
- boolean _hasActivities) {
- isProc = true;
- label = _label;
- shortLabel = _shortLabel;
- pss = _pss;
- swapPss = _swapPss;
- id = _id;
- hasActivities = _hasActivities;
+ MemItem(String label, String shortLabel, long pss, long swapPss, long rss, int id,
+ boolean hasActivities) {
+ this.isProc = true;
+ this.label = label;
+ this.shortLabel = shortLabel;
+ this.pss = pss;
+ this.swapPss = swapPss;
+ this.mRss = rss;
+ this.id = id;
+ this.hasActivities = hasActivities;
}
- public MemItem(String _label, String _shortLabel, long _pss, long _swapPss, int _id) {
- isProc = false;
- label = _label;
- shortLabel = _shortLabel;
- pss = _pss;
- swapPss = _swapPss;
- id = _id;
- hasActivities = false;
+ MemItem(String label, String shortLabel, long pss, long swapPss, long rss, int id) {
+ this.isProc = false;
+ this.label = label;
+ this.shortLabel = shortLabel;
+ this.pss = pss;
+ this.swapPss = swapPss;
+ this.mRss = rss;
+ this.id = id;
+ this.hasActivities = false;
}
}
- private static void sortMemItems(List<MemItem> items) {
+ private static void sortMemItems(List<MemItem> items, final boolean pss) {
Collections.sort(items, new Comparator<MemItem>() {
@Override
public int compare(MemItem lhs, MemItem rhs) {
- if (lhs.pss < rhs.pss) {
+ long lss = pss ? lhs.pss : lhs.mRss;
+ long rss = pss ? rhs.pss : rhs.mRss;
+ if (lss < rss) {
return 1;
- } else if (lhs.pss > rhs.pss) {
+ } else if (lss > rss) {
return -1;
}
return 0;
@@ -12146,40 +12155,44 @@
}
static final void dumpMemItems(PrintWriter pw, String prefix, String tag,
- ArrayList<MemItem> items, boolean sort, boolean isCompact, boolean dumpSwapPss) {
+ ArrayList<MemItem> items, boolean sort, boolean isCompact, boolean dumpPss,
+ boolean dumpSwapPss) {
if (sort && !isCompact) {
- sortMemItems(items);
+ sortMemItems(items, dumpPss);
}
for (int i=0; i<items.size(); i++) {
MemItem mi = items.get(i);
if (!isCompact) {
- if (dumpSwapPss) {
+ if (dumpPss && dumpSwapPss) {
pw.printf("%s%s: %-60s (%s in swap)\n", prefix, stringifyKBSize(mi.pss),
mi.label, stringifyKBSize(mi.swapPss));
} else {
- pw.printf("%s%s: %s\n", prefix, stringifyKBSize(mi.pss), mi.label);
+ pw.printf("%s%s: %s\n", prefix, stringifyKBSize(dumpPss ? mi.pss : mi.mRss),
+ mi.label);
}
} else if (mi.isProc) {
pw.print("proc,"); pw.print(tag); pw.print(","); pw.print(mi.shortLabel);
- pw.print(","); pw.print(mi.id); pw.print(","); pw.print(mi.pss); pw.print(",");
+ pw.print(","); pw.print(mi.id); pw.print(",");
+ pw.print(dumpPss ? mi.pss : mi.mRss); pw.print(",");
pw.print(dumpSwapPss ? mi.swapPss : "N/A");
pw.println(mi.hasActivities ? ",a" : ",e");
} else {
pw.print(tag); pw.print(","); pw.print(mi.shortLabel); pw.print(",");
- pw.print(mi.pss); pw.print(","); pw.println(dumpSwapPss ? mi.swapPss : "N/A");
+ pw.print(dumpPss ? mi.pss : mi.mRss); pw.print(",");
+ pw.println(dumpSwapPss ? mi.swapPss : "N/A");
}
if (mi.subitems != null) {
dumpMemItems(pw, prefix + " ", mi.shortLabel, mi.subitems,
- true, isCompact, dumpSwapPss);
+ true, isCompact, dumpPss, dumpSwapPss);
}
}
}
static final void dumpMemItems(ProtoOutputStream proto, long fieldId, String tag,
- ArrayList<MemItem> items, boolean sort, boolean dumpSwapPss) {
+ ArrayList<MemItem> items, boolean sort, boolean dumpPss, boolean dumpSwapPss) {
if (sort) {
- sortMemItems(items);
+ sortMemItems(items, dumpPss);
}
for (int i=0; i<items.size(); i++) {
@@ -12191,13 +12204,17 @@
proto.write(MemInfoDumpProto.MemItem.IS_PROC, mi.isProc);
proto.write(MemInfoDumpProto.MemItem.ID, mi.id);
proto.write(MemInfoDumpProto.MemItem.HAS_ACTIVITIES, mi.hasActivities);
- proto.write(MemInfoDumpProto.MemItem.PSS_KB, mi.pss);
+ if (dumpPss) {
+ proto.write(MemInfoDumpProto.MemItem.PSS_KB, mi.pss);
+ } else {
+ proto.write(MemInfoDumpProto.MemItem.RSS_KB, mi.mRss);
+ }
if (dumpSwapPss) {
proto.write(MemInfoDumpProto.MemItem.SWAP_PSS_KB, mi.swapPss);
}
if (mi.subitems != null) {
dumpMemItems(proto, MemInfoDumpProto.MemItem.SUB_ITEMS, mi.shortLabel, mi.subitems,
- true, dumpSwapPss);
+ true, dumpPss, dumpSwapPss);
}
proto.end(token);
}
@@ -12496,24 +12513,32 @@
final SparseArray<MemItem> procMemsMap = new SparseArray<MemItem>();
long nativePss = 0;
long nativeSwapPss = 0;
+ long nativeRss = 0;
long dalvikPss = 0;
long dalvikSwapPss = 0;
+ long dalvikRss = 0;
long[] dalvikSubitemPss = opts.dumpDalvik ? new long[Debug.MemoryInfo.NUM_DVK_STATS] :
EmptyArray.LONG;
long[] dalvikSubitemSwapPss = opts.dumpDalvik ? new long[Debug.MemoryInfo.NUM_DVK_STATS] :
EmptyArray.LONG;
+ long[] dalvikSubitemRss = opts.dumpDalvik ? new long[Debug.MemoryInfo.NUM_DVK_STATS] :
+ EmptyArray.LONG;
long otherPss = 0;
long otherSwapPss = 0;
+ long otherRss = 0;
long[] miscPss = new long[Debug.MemoryInfo.NUM_OTHER_STATS];
long[] miscSwapPss = new long[Debug.MemoryInfo.NUM_OTHER_STATS];
+ long[] miscRss = new long[Debug.MemoryInfo.NUM_OTHER_STATS];
long oomPss[] = new long[DUMP_MEM_OOM_LABEL.length];
long oomSwapPss[] = new long[DUMP_MEM_OOM_LABEL.length];
+ long[] oomRss = new long[DUMP_MEM_OOM_LABEL.length];
ArrayList<MemItem>[] oomProcs = (ArrayList<MemItem>[])
new ArrayList[DUMP_MEM_OOM_LABEL.length];
long totalPss = 0;
long totalSwapPss = 0;
+ long totalRss = 0;
long cachedPss = 0;
long cachedSwapPss = 0;
boolean hasSwapPss = false;
@@ -12553,6 +12578,7 @@
mi.dalvikPss = (int)Debug.getPss(pid, tmpLong, null);
endTime = SystemClock.currentThreadTimeMillis();
mi.dalvikPrivateDirty = (int)tmpLong[0];
+ mi.dalvikRss = (int) tmpLong[2];
}
if (opts.dumpDetails) {
if (opts.localOnly) {
@@ -12613,22 +12639,27 @@
if (!opts.isCheckinRequest && mi != null) {
totalPss += myTotalPss;
totalSwapPss += myTotalSwapPss;
+ totalRss += myTotalRss;
MemItem pssItem = new MemItem(r.processName + " (pid " + pid +
(hasActivities ? " / activities)" : ")"), r.processName, myTotalPss,
- myTotalSwapPss, pid, hasActivities);
+ myTotalSwapPss, myTotalRss, pid, hasActivities);
procMems.add(pssItem);
procMemsMap.put(pid, pssItem);
nativePss += mi.nativePss;
nativeSwapPss += mi.nativeSwappedOutPss;
+ nativeRss += mi.nativeRss;
dalvikPss += mi.dalvikPss;
dalvikSwapPss += mi.dalvikSwappedOutPss;
+ dalvikRss += mi.dalvikRss;
for (int j=0; j<dalvikSubitemPss.length; j++) {
dalvikSubitemPss[j] += mi.getOtherPss(Debug.MemoryInfo.NUM_OTHER_STATS + j);
dalvikSubitemSwapPss[j] +=
mi.getOtherSwappedOutPss(Debug.MemoryInfo.NUM_OTHER_STATS + j);
+ dalvikSubitemRss[j] += mi.getOtherRss(Debug.MemoryInfo.NUM_OTHER_STATS + j);
}
otherPss += mi.otherPss;
+ otherRss += mi.otherRss;
otherSwapPss += mi.otherSwappedOutPss;
for (int j=0; j<Debug.MemoryInfo.NUM_OTHER_STATS; j++) {
long mem = mi.getOtherPss(j);
@@ -12637,6 +12668,9 @@
mem = mi.getOtherSwappedOutPss(j);
miscSwapPss[j] += mem;
otherSwapPss -= mem;
+ mem = mi.getOtherRss(j);
+ miscRss[j] += mem;
+ otherRss -= mem;
}
if (oomAdj >= ProcessList.CACHED_APP_MIN_ADJ) {
@@ -12654,6 +12688,7 @@
oomProcs[oomIndex] = new ArrayList<MemItem>();
}
oomProcs[oomIndex].add(pssItem);
+ oomRss[oomIndex] += myTotalRss;
break;
}
}
@@ -12685,25 +12720,33 @@
final long myTotalPss = mi.getTotalPss();
final long myTotalSwapPss = mi.getTotalSwappedOutPss();
+ final long myTotalRss = mi.getTotalRss();
totalPss += myTotalPss;
totalSwapPss += myTotalSwapPss;
+ totalRss += myTotalRss;
nativeProcTotalPss += myTotalPss;
MemItem pssItem = new MemItem(st.name + " (pid " + st.pid + ")",
- st.name, myTotalPss, mi.getSummaryTotalSwapPss(), st.pid, false);
+ st.name, myTotalPss, mi.getSummaryTotalSwapPss(), myTotalRss,
+ st.pid, false);
procMems.add(pssItem);
nativePss += mi.nativePss;
nativeSwapPss += mi.nativeSwappedOutPss;
+ nativeRss += mi.nativeRss;
dalvikPss += mi.dalvikPss;
dalvikSwapPss += mi.dalvikSwappedOutPss;
+ dalvikRss += mi.dalvikRss;
for (int j=0; j<dalvikSubitemPss.length; j++) {
dalvikSubitemPss[j] += mi.getOtherPss(Debug.MemoryInfo.NUM_OTHER_STATS + j);
dalvikSubitemSwapPss[j] +=
mi.getOtherSwappedOutPss(Debug.MemoryInfo.NUM_OTHER_STATS + j);
+ dalvikSubitemRss[j] += mi.getOtherRss(Debug.MemoryInfo.NUM_OTHER_STATS
+ + j);
}
otherPss += mi.otherPss;
otherSwapPss += mi.otherSwappedOutPss;
+ otherRss += mi.otherRss;
for (int j=0; j<Debug.MemoryInfo.NUM_OTHER_STATS; j++) {
long mem = mi.getOtherPss(j);
miscPss[j] += mem;
@@ -12711,6 +12754,9 @@
mem = mi.getOtherSwappedOutPss(j);
miscSwapPss[j] += mem;
otherSwapPss -= mem;
+ mem = mi.getOtherRss(j);
+ miscRss[j] += mem;
+ otherRss -= mem;
}
oomPss[0] += myTotalPss;
oomSwapPss[0] += myTotalSwapPss;
@@ -12718,19 +12764,21 @@
oomProcs[0] = new ArrayList<MemItem>();
}
oomProcs[0].add(pssItem);
+ oomRss[0] += myTotalRss;
}
}
}
ArrayList<MemItem> catMems = new ArrayList<MemItem>();
- catMems.add(new MemItem("Native", "Native", nativePss, nativeSwapPss, -1));
+ catMems.add(new MemItem("Native", "Native", nativePss, nativeSwapPss, nativeRss, -1));
final int dalvikId = -2;
- catMems.add(new MemItem("Dalvik", "Dalvik", dalvikPss, dalvikSwapPss, dalvikId));
- catMems.add(new MemItem("Unknown", "Unknown", otherPss, otherSwapPss, -3));
+ catMems.add(new MemItem("Dalvik", "Dalvik", dalvikPss, dalvikSwapPss, dalvikRss,
+ dalvikId));
+ catMems.add(new MemItem("Unknown", "Unknown", otherPss, otherSwapPss, otherRss, -3));
for (int j=0; j<Debug.MemoryInfo.NUM_OTHER_STATS; j++) {
String label = Debug.MemoryInfo.getOtherLabel(j);
- catMems.add(new MemItem(label, label, miscPss[j], miscSwapPss[j], j));
+ catMems.add(new MemItem(label, label, miscPss[j], miscSwapPss[j], miscRss[j], j));
}
if (dalvikSubitemPss.length > 0) {
// Add dalvik subitems.
@@ -12756,7 +12804,7 @@
final String name = Debug.MemoryInfo.getOtherLabel(
Debug.MemoryInfo.NUM_OTHER_STATS + j);
memItem.subitems.add(new MemItem(name, name, dalvikSubitemPss[j],
- dalvikSubitemSwapPss[j], j));
+ dalvikSubitemSwapPss[j], dalvikSubitemRss[j], j));
}
}
}
@@ -12766,31 +12814,53 @@
if (oomPss[j] != 0) {
String label = opts.isCompact ? DUMP_MEM_OOM_COMPACT_LABEL[j]
: DUMP_MEM_OOM_LABEL[j];
- MemItem item = new MemItem(label, label, oomPss[j], oomSwapPss[j],
+ MemItem item = new MemItem(label, label, oomPss[j], oomSwapPss[j], oomRss[j],
DUMP_MEM_OOM_ADJ[j]);
item.subitems = oomProcs[j];
oomMems.add(item);
}
}
-
+ if (!opts.isCompact) {
+ pw.println();
+ }
+ if (!brief && !opts.oomOnly && !opts.isCompact) {
+ pw.println();
+ pw.println("Total RSS by process:");
+ dumpMemItems(pw, " ", "proc", procMems, true, opts.isCompact, false, false);
+ pw.println();
+ }
+ if (!opts.isCompact) {
+ pw.println("Total RSS by OOM adjustment:");
+ }
+ dumpMemItems(pw, " ", "oom", oomMems, false, opts.isCompact, false, false);
+ if (!brief && !opts.oomOnly) {
+ PrintWriter out = categoryPw != null ? categoryPw : pw;
+ if (!opts.isCompact) {
+ out.println();
+ out.println("Total RSS by category:");
+ }
+ dumpMemItems(out, " ", "cat", catMems, true, opts.isCompact, false, false);
+ }
opts.dumpSwapPss = opts.dumpSwapPss && hasSwapPss && totalSwapPss != 0;
if (!brief && !opts.oomOnly && !opts.isCompact) {
pw.println();
pw.println("Total PSS by process:");
- dumpMemItems(pw, " ", "proc", procMems, true, opts.isCompact, opts.dumpSwapPss);
+ dumpMemItems(pw, " ", "proc", procMems, true, opts.isCompact, true,
+ opts.dumpSwapPss);
pw.println();
}
if (!opts.isCompact) {
pw.println("Total PSS by OOM adjustment:");
}
- dumpMemItems(pw, " ", "oom", oomMems, false, opts.isCompact, opts.dumpSwapPss);
+ dumpMemItems(pw, " ", "oom", oomMems, false, opts.isCompact, true, opts.dumpSwapPss);
if (!brief && !opts.oomOnly) {
PrintWriter out = categoryPw != null ? categoryPw : pw;
if (!opts.isCompact) {
out.println();
out.println("Total PSS by category:");
}
- dumpMemItems(out, " ", "cat", catMems, true, opts.isCompact, opts.dumpSwapPss);
+ dumpMemItems(out, " ", "cat", catMems, true, opts.isCompact, true,
+ opts.dumpSwapPss);
}
if (!opts.isCompact) {
pw.println();
@@ -13009,24 +13079,32 @@
final SparseArray<MemItem> procMemsMap = new SparseArray<MemItem>();
long nativePss = 0;
long nativeSwapPss = 0;
+ long nativeRss = 0;
long dalvikPss = 0;
long dalvikSwapPss = 0;
+ long dalvikRss = 0;
long[] dalvikSubitemPss = opts.dumpDalvik ? new long[Debug.MemoryInfo.NUM_DVK_STATS] :
EmptyArray.LONG;
long[] dalvikSubitemSwapPss = opts.dumpDalvik ? new long[Debug.MemoryInfo.NUM_DVK_STATS] :
EmptyArray.LONG;
+ long[] dalvikSubitemRss = opts.dumpDalvik ? new long[Debug.MemoryInfo.NUM_DVK_STATS] :
+ EmptyArray.LONG;
long otherPss = 0;
long otherSwapPss = 0;
+ long otherRss = 0;
long[] miscPss = new long[Debug.MemoryInfo.NUM_OTHER_STATS];
long[] miscSwapPss = new long[Debug.MemoryInfo.NUM_OTHER_STATS];
+ long[] miscRss = new long[Debug.MemoryInfo.NUM_OTHER_STATS];
long oomPss[] = new long[DUMP_MEM_OOM_LABEL.length];
long oomSwapPss[] = new long[DUMP_MEM_OOM_LABEL.length];
+ long[] oomRss = new long[DUMP_MEM_OOM_LABEL.length];
ArrayList<MemItem>[] oomProcs = (ArrayList<MemItem>[])
new ArrayList[DUMP_MEM_OOM_LABEL.length];
long totalPss = 0;
long totalSwapPss = 0;
+ long totalRss = 0;
long cachedPss = 0;
long cachedSwapPss = 0;
boolean hasSwapPss = false;
@@ -13065,6 +13143,7 @@
mi.dalvikPss = (int) Debug.getPss(pid, tmpLong, null);
endTime = SystemClock.currentThreadTimeMillis();
mi.dalvikPrivateDirty = (int) tmpLong[0];
+ mi.dalvikRss = (int) tmpLong[2];
}
if (opts.dumpDetails) {
if (opts.localOnly) {
@@ -13120,22 +13199,27 @@
if (!opts.isCheckinRequest && mi != null) {
totalPss += myTotalPss;
totalSwapPss += myTotalSwapPss;
+ totalRss += myTotalRss;
MemItem pssItem = new MemItem(r.processName + " (pid " + pid +
(hasActivities ? " / activities)" : ")"), r.processName, myTotalPss,
- myTotalSwapPss, pid, hasActivities);
+ myTotalSwapPss, myTotalRss, pid, hasActivities);
procMems.add(pssItem);
procMemsMap.put(pid, pssItem);
nativePss += mi.nativePss;
nativeSwapPss += mi.nativeSwappedOutPss;
+ nativeRss += mi.nativeRss;
dalvikPss += mi.dalvikPss;
dalvikSwapPss += mi.dalvikSwappedOutPss;
+ dalvikRss += mi.dalvikRss;
for (int j=0; j<dalvikSubitemPss.length; j++) {
dalvikSubitemPss[j] += mi.getOtherPss(Debug.MemoryInfo.NUM_OTHER_STATS + j);
dalvikSubitemSwapPss[j] +=
mi.getOtherSwappedOutPss(Debug.MemoryInfo.NUM_OTHER_STATS + j);
+ dalvikSubitemRss[j] += mi.getOtherRss(Debug.MemoryInfo.NUM_OTHER_STATS + j);
}
otherPss += mi.otherPss;
+ otherRss += mi.otherRss;
otherSwapPss += mi.otherSwappedOutPss;
for (int j=0; j<Debug.MemoryInfo.NUM_OTHER_STATS; j++) {
long mem = mi.getOtherPss(j);
@@ -13144,6 +13228,9 @@
mem = mi.getOtherSwappedOutPss(j);
miscSwapPss[j] += mem;
otherSwapPss -= mem;
+ mem = mi.getOtherRss(j);
+ miscRss[j] += mem;
+ otherRss -= mem;
}
if (oomAdj >= ProcessList.CACHED_APP_MIN_ADJ) {
@@ -13161,6 +13248,7 @@
oomProcs[oomIndex] = new ArrayList<MemItem>();
}
oomProcs[oomIndex].add(pssItem);
+ oomRss[oomIndex] += myTotalRss;
break;
}
}
@@ -13191,24 +13279,33 @@
final long myTotalPss = mi.getTotalPss();
final long myTotalSwapPss = mi.getTotalSwappedOutPss();
+ final long myTotalRss = mi.getTotalRss();
totalPss += myTotalPss;
+ totalSwapPss += myTotalSwapPss;
+ totalRss += myTotalRss;
nativeProcTotalPss += myTotalPss;
MemItem pssItem = new MemItem(st.name + " (pid " + st.pid + ")",
- st.name, myTotalPss, mi.getSummaryTotalSwapPss(), st.pid, false);
+ st.name, myTotalPss, mi.getSummaryTotalSwapPss(), myTotalRss,
+ st.pid, false);
procMems.add(pssItem);
nativePss += mi.nativePss;
nativeSwapPss += mi.nativeSwappedOutPss;
+ nativeRss += mi.nativeRss;
dalvikPss += mi.dalvikPss;
dalvikSwapPss += mi.dalvikSwappedOutPss;
+ dalvikRss += mi.dalvikRss;
for (int j=0; j<dalvikSubitemPss.length; j++) {
dalvikSubitemPss[j] += mi.getOtherPss(Debug.MemoryInfo.NUM_OTHER_STATS + j);
dalvikSubitemSwapPss[j] +=
mi.getOtherSwappedOutPss(Debug.MemoryInfo.NUM_OTHER_STATS + j);
+ dalvikSubitemRss[j] += mi.getOtherRss(Debug.MemoryInfo.NUM_OTHER_STATS
+ + j);
}
otherPss += mi.otherPss;
otherSwapPss += mi.otherSwappedOutPss;
+ otherRss += mi.otherRss;
for (int j=0; j<Debug.MemoryInfo.NUM_OTHER_STATS; j++) {
long mem = mi.getOtherPss(j);
miscPss[j] += mem;
@@ -13216,6 +13313,9 @@
mem = mi.getOtherSwappedOutPss(j);
miscSwapPss[j] += mem;
otherSwapPss -= mem;
+ mem = mi.getOtherRss(j);
+ miscRss[j] += mem;
+ otherRss -= mem;
}
oomPss[0] += myTotalPss;
oomSwapPss[0] += myTotalSwapPss;
@@ -13223,19 +13323,21 @@
oomProcs[0] = new ArrayList<MemItem>();
}
oomProcs[0].add(pssItem);
+ oomRss[0] += myTotalRss;
}
}
}
ArrayList<MemItem> catMems = new ArrayList<MemItem>();
- catMems.add(new MemItem("Native", "Native", nativePss, nativeSwapPss, -1));
+ catMems.add(new MemItem("Native", "Native", nativePss, nativeSwapPss, nativeRss, -1));
final int dalvikId = -2;
- catMems.add(new MemItem("Dalvik", "Dalvik", dalvikPss, dalvikSwapPss, dalvikId));
- catMems.add(new MemItem("Unknown", "Unknown", otherPss, otherSwapPss, -3));
+ catMems.add(new MemItem("Dalvik", "Dalvik", dalvikPss, dalvikSwapPss, dalvikRss,
+ dalvikId));
+ catMems.add(new MemItem("Unknown", "Unknown", otherPss, otherSwapPss, otherRss, -3));
for (int j=0; j<Debug.MemoryInfo.NUM_OTHER_STATS; j++) {
String label = Debug.MemoryInfo.getOtherLabel(j);
- catMems.add(new MemItem(label, label, miscPss[j], miscSwapPss[j], j));
+ catMems.add(new MemItem(label, label, miscPss[j], miscSwapPss[j], miscRss[j], j));
}
if (dalvikSubitemPss.length > 0) {
// Add dalvik subitems.
@@ -13261,7 +13363,7 @@
final String name = Debug.MemoryInfo.getOtherLabel(
Debug.MemoryInfo.NUM_OTHER_STATS + j);
memItem.subitems.add(new MemItem(name, name, dalvikSubitemPss[j],
- dalvikSubitemSwapPss[j], j));
+ dalvikSubitemSwapPss[j], dalvikSubitemRss[j], j));
}
}
}
@@ -13271,23 +13373,34 @@
if (oomPss[j] != 0) {
String label = opts.isCompact ? DUMP_MEM_OOM_COMPACT_LABEL[j]
: DUMP_MEM_OOM_LABEL[j];
- MemItem item = new MemItem(label, label, oomPss[j], oomSwapPss[j],
+ MemItem item = new MemItem(label, label, oomPss[j], oomSwapPss[j], oomRss[j],
DUMP_MEM_OOM_ADJ[j]);
item.subitems = oomProcs[j];
oomMems.add(item);
}
}
+ if (!opts.oomOnly) {
+ dumpMemItems(proto, MemInfoDumpProto.TOTAL_RSS_BY_PROCESS, "proc",
+ procMems, true, false, false);
+ }
+ dumpMemItems(proto, MemInfoDumpProto.TOTAL_RSS_BY_OOM_ADJUSTMENT, "oom",
+ oomMems, false, false, false);
+ if (!brief && !opts.oomOnly) {
+ dumpMemItems(proto, MemInfoDumpProto.TOTAL_RSS_BY_CATEGORY, "cat",
+ catMems, true, false, false);
+ }
+
opts.dumpSwapPss = opts.dumpSwapPss && hasSwapPss && totalSwapPss != 0;
if (!opts.oomOnly) {
dumpMemItems(proto, MemInfoDumpProto.TOTAL_PSS_BY_PROCESS, "proc",
- procMems, true, opts.dumpSwapPss);
+ procMems, true, true, opts.dumpSwapPss);
}
dumpMemItems(proto, MemInfoDumpProto.TOTAL_PSS_BY_OOM_ADJUSTMENT, "oom",
- oomMems, false, opts.dumpSwapPss);
+ oomMems, false, true, opts.dumpSwapPss);
if (!brief && !opts.oomOnly) {
dumpMemItems(proto, MemInfoDumpProto.TOTAL_PSS_BY_CATEGORY, "cat",
- catMems, true, opts.dumpSwapPss);
+ catMems, true, true, opts.dumpSwapPss);
}
MemInfoReader memInfo = new MemInfoReader();
memInfo.readMemInfo();
@@ -18894,9 +19007,14 @@
@VisibleForTesting
public static class Injector {
private NetworkManagementInternal mNmi;
+ private Context mContext;
+
+ public Injector(Context context) {
+ mContext = context;
+ }
public Context getContext() {
- return null;
+ return mContext;
}
public AppOpsService getAppOpsService(File file, Handler handler) {
diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java
index 97e5293..7a3d3c2 100644
--- a/services/core/java/com/android/server/am/OomAdjuster.java
+++ b/services/core/java/com/android/server/am/OomAdjuster.java
@@ -1102,10 +1102,13 @@
// this gives us a baseline and makes sure we don't get into an
// infinite recursion. If we're re-evaluating due to cycles, use the previously computed
// values.
- app.setCurRawAdj(!cycleReEval ? adj : Math.min(adj, app.getCurRawAdj()));
- app.setCurRawProcState(!cycleReEval
- ? procState
- : Math.min(procState, app.getCurRawProcState()));
+ if (cycleReEval) {
+ procState = Math.min(procState, app.getCurRawProcState());
+ adj = Math.min(adj, app.getCurRawAdj());
+ schedGroup = Math.max(schedGroup, app.getCurrentSchedulingGroup());
+ }
+ app.setCurRawAdj(adj);
+ app.setCurRawProcState(procState);
app.hasStartedServices = false;
app.adjSeq = mAdjSeq;
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index 3007016..6d6a148 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -18,9 +18,11 @@
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;
import static android.app.AppOpsManager.OP_FLAGS_ALL;
import static android.app.AppOpsManager.OP_NONE;
import static android.app.AppOpsManager.OP_PLAY_AUDIO;
+import static android.app.AppOpsManager.OP_RECORD_AUDIO;
import static android.app.AppOpsManager.UID_STATE_BACKGROUND;
import static android.app.AppOpsManager.UID_STATE_CACHED;
import static android.app.AppOpsManager.UID_STATE_FOREGROUND;
@@ -173,6 +175,12 @@
UID_STATE_CACHED, // ActivityManager.PROCESS_STATE_NONEXISTENT
};
+ private static final int[] OPS_RESTRICTED_ON_SUSPEND = {
+ OP_PLAY_AUDIO,
+ OP_RECORD_AUDIO,
+ OP_CAMERA,
+ };
+
Context mContext;
final AtomicFile mFile;
final Handler mHandler;
@@ -798,7 +806,9 @@
final String changedPkg = changedPkgs[i];
// We trust packagemanager to insert matching uid and packageNames in the
// extras
- notifyOpChanged(callbacks, OP_PLAY_AUDIO, changedUid, changedPkg);
+ for (int code : OPS_RESTRICTED_ON_SUSPEND) {
+ notifyOpChanged(callbacks, code, changedUid, changedPkg);
+ }
}
}
}, packageSuspendFilter);
@@ -1759,6 +1769,9 @@
return AppOpsManager.opToDefaultMode(code);
}
+ if (isOpRestrictedDueToSuspend(code, packageName, uid)) {
+ return AppOpsManager.MODE_IGNORED;
+ }
synchronized (this) {
if (isOpRestrictedLocked(uid, code, packageName, isPrivileged)) {
return AppOpsManager.MODE_IGNORED;
@@ -1792,20 +1805,6 @@
}
private int checkAudioOperationImpl(int code, int usage, int uid, String packageName) {
- boolean suspended;
- try {
- suspended = isPackageSuspendedForUser(packageName, uid);
- } catch (IllegalArgumentException ex) {
- // Package not found.
- suspended = false;
- }
-
- if (suspended) {
- Slog.i(TAG, "Audio disabled for suspended package=" + packageName
- + " for uid=" + uid);
- return AppOpsManager.MODE_IGNORED;
- }
-
synchronized (this) {
final int mode = checkRestrictionLocked(code, usage, uid, packageName);
if (mode != AppOpsManager.MODE_ALLOWED) {
@@ -1815,18 +1814,6 @@
return checkOperation(code, uid, packageName);
}
- private boolean isPackageSuspendedForUser(String pkg, int uid) {
- final long identity = Binder.clearCallingIdentity();
- try {
- return AppGlobals.getPackageManager().isPackageSuspendedForUser(
- pkg, UserHandle.getUserId(uid));
- } catch (RemoteException re) {
- throw new SecurityException("Could not talk to package manager service");
- } finally {
- Binder.restoreCallingIdentity(identity);
- }
- }
-
private int checkRestrictionLocked(int code, int usage, int uid, String packageName) {
final SparseArray<Restriction> usageRestrictions = mAudioRestrictions.get(code);
if (usageRestrictions != null) {
@@ -2654,6 +2641,12 @@
return op;
}
+ private boolean isOpRestrictedDueToSuspend(int code, String packageName, int uid) {
+ final PackageManagerInternal pmi = LocalServices.getService(PackageManagerInternal.class);
+ return ArrayUtils.contains(OPS_RESTRICTED_ON_SUSPEND, code)
+ && pmi.isPackageSuspended(packageName, UserHandle.getUserId(uid));
+ }
+
private boolean isOpRestrictedLocked(int uid, int code, String packageName,
boolean isPrivileged) {
int userHandle = UserHandle.getUserId(uid);
diff --git a/services/core/java/com/android/server/broadcastradio/hal2/TunerSession.java b/services/core/java/com/android/server/broadcastradio/hal2/TunerSession.java
index 764fca9..7ab3bdd 100644
--- a/services/core/java/com/android/server/broadcastradio/hal2/TunerSession.java
+++ b/services/core/java/com/android/server/broadcastradio/hal2/TunerSession.java
@@ -31,6 +31,7 @@
import android.util.MutableInt;
import android.util.Slog;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
@@ -186,6 +187,12 @@
@Override
public void startProgramListUpdates(ProgramList.Filter filter) throws RemoteException {
+ // If the AIDL client provides a null filter, it wants all updates, so use the most broad
+ // filter.
+ if (filter == null) {
+ filter = new ProgramList.Filter(new HashSet<Integer>(),
+ new HashSet<android.hardware.radio.ProgramSelector.Identifier>(), true, false);
+ }
synchronized (mLock) {
checkNotClosedLocked();
mProgramInfoCache = new ProgramInfoCache(filter);
diff --git a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
index 8d1a802..96b7cb3 100644
--- a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
+++ b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
@@ -580,10 +580,12 @@
}
if (newExpiry > 0) {
- mLingerMessage = mConnService.makeWakeupMessage(
+ mLingerMessage = new WakeupMessage(
mContext, mHandler,
- "NETWORK_LINGER_COMPLETE." + network.netId,
- EVENT_NETWORK_LINGER_COMPLETE, this);
+ "NETWORK_LINGER_COMPLETE." + network.netId /* cmdName */,
+ EVENT_NETWORK_LINGER_COMPLETE /* cmd */,
+ 0 /* arg1 (unused) */, 0 /* arg2 (unused) */,
+ this /* obj (NetworkAgentInfo) */);
mLingerMessage.schedule(newExpiry);
}
diff --git a/services/core/java/com/android/server/display/DisplayModeDirector.java b/services/core/java/com/android/server/display/DisplayModeDirector.java
index c45a314..7648636 100644
--- a/services/core/java/com/android/server/display/DisplayModeDirector.java
+++ b/services/core/java/com/android/server/display/DisplayModeDirector.java
@@ -680,6 +680,7 @@
@Override
public void onDisplayChanged(int displayId) {
updateDisplayModes(displayId);
+ mBrightnessObserver.onDisplayChanged(displayId);
}
private void updateDisplayModes(int displayId) {
@@ -734,8 +735,6 @@
private AmbientFilter mAmbientFilter;
private final Context mContext;
- private ScreenStateReceiver mScreenStateReceiver;
-
// Enable light sensor only when screen is on, peak refresh rate enabled and low power mode
// off. After initialization, these states will be updated from the same handler thread.
private boolean mScreenOn = false;
@@ -793,11 +792,7 @@
mSensorManager = sensorManager;
mLightSensor = lightSensor;
- // Intent.ACTION_SCREEN_ON is not sticky. Check current screen status.
- if (mContext.getSystemService(PowerManager.class).isInteractive()) {
- onScreenOn(true);
- }
- mScreenStateReceiver = new ScreenStateReceiver(mContext);
+ onScreenOn(isDefaultDisplayOn());
}
}
@@ -822,6 +817,12 @@
}
}
+ public void onDisplayChanged(int displayId) {
+ if (displayId == Display.DEFAULT_DISPLAY) {
+ onScreenOn(isDefaultDisplayOn());
+ }
+ }
+
public void dumpLocked(PrintWriter pw) {
pw.println(" BrightnessObserver");
@@ -891,8 +892,6 @@
}
private void onScreenOn(boolean on) {
- // Not check mShouldObserveAmbientChange because Screen status receiver is registered
- // only when it is true.
if (mScreenOn != on) {
mScreenOn = on;
updateSensorStatus();
@@ -913,6 +912,13 @@
}
}
+ private boolean isDefaultDisplayOn() {
+ final Display display = mContext.getSystemService(DisplayManager.class)
+ .getDisplay(Display.DEFAULT_DISPLAY);
+ return display.getState() != Display.STATE_OFF
+ && mContext.getSystemService(PowerManager.class).isInteractive();
+ }
+
private final class LightSensorEventListener implements SensorEventListener {
final private static int INJECT_EVENTS_INTERVAL_MS = LIGHT_SENSOR_RATE_MS;
private float mLastSensorData;
@@ -991,20 +997,5 @@
}
};
};
-
- private final class ScreenStateReceiver extends BroadcastReceiver {
- public ScreenStateReceiver(Context context) {
- IntentFilter filter = new IntentFilter();
- filter.addAction(Intent.ACTION_SCREEN_OFF);
- filter.addAction(Intent.ACTION_SCREEN_ON);
- filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
- context.registerReceiver(this, filter, null, mHandler);
- }
-
- @Override
- public void onReceive(Context context, Intent intent) {
- onScreenOn(Intent.ACTION_SCREEN_ON.equals(intent.getAction()));
- }
- }
}
}
diff --git a/services/core/java/com/android/server/media/OWNERS b/services/core/java/com/android/server/media/OWNERS
index 4bc9373..b460cb5 100644
--- a/services/core/java/com/android/server/media/OWNERS
+++ b/services/core/java/com/android/server/media/OWNERS
@@ -2,5 +2,6 @@
hdmoon@google.com
insun@google.com
jaewan@google.com
+klhyun@google.com
lajos@google.com
sungsoo@google.com
diff --git a/services/core/java/com/android/server/om/IdmapDaemon.java b/services/core/java/com/android/server/om/IdmapDaemon.java
new file mode 100644
index 0000000..91824c3
--- /dev/null
+++ b/services/core/java/com/android/server/om/IdmapDaemon.java
@@ -0,0 +1,194 @@
+/*
+ * 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.om;
+
+import static android.content.Context.IDMAP_SERVICE;
+
+import static com.android.server.om.OverlayManagerService.DEBUG;
+import static com.android.server.om.OverlayManagerService.TAG;
+
+import android.os.IBinder;
+import android.os.IIdmap2;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.SystemProperties;
+import android.util.Slog;
+
+import com.android.server.FgThread;
+
+import java.util.concurrent.FutureTask;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * To prevent idmap2d from continuously running, the idmap daemon will terminate after 10
+ * seconds without a transaction.
+ **/
+class IdmapDaemon {
+ // The amount of time in milliseconds to wait after a transaction to the idmap service is made
+ // before stopping the service.
+ private static final int SERVICE_TIMEOUT_MS = 10000;
+
+ // The amount of time in milliseconds to wait when attempting to connect to idmap service.
+ private static final int SERVICE_CONNECT_TIMEOUT_MS = 5000;
+
+ private static final Object IDMAP_TOKEN = new Object();
+ private static final String IDMAP_DAEMON = "idmap2d";
+
+ private static IdmapDaemon sInstance;
+ private volatile IIdmap2 mService;
+ private final AtomicInteger mOpenedCount = new AtomicInteger();
+
+ /**
+ * An {@link AutoCloseable} connection to the idmap service. When the connection is closed or
+ * finalized, the idmap service will be stopped after a period of time unless another connection
+ * to the service is open.
+ **/
+ private class Connection implements AutoCloseable {
+ private boolean mOpened = true;
+
+ private Connection() {
+ synchronized (IDMAP_TOKEN) {
+ mOpenedCount.incrementAndGet();
+ }
+ }
+
+ @Override
+ public void close() {
+ synchronized (IDMAP_TOKEN) {
+ if (!mOpened) {
+ return;
+ }
+
+ mOpened = false;
+ if (mOpenedCount.decrementAndGet() != 0) {
+ // Only post the callback to stop the service if the service does not have an
+ // open connection.
+ return;
+ }
+
+ FgThread.getHandler().postDelayed(() -> {
+ synchronized (IDMAP_TOKEN) {
+ // Only stop the service if the service does not have an open connection.
+ if (mService == null || mOpenedCount.get() != 0) {
+ return;
+ }
+
+ stopIdmapService();
+ mService = null;
+ }
+ }, IDMAP_TOKEN, SERVICE_TIMEOUT_MS);
+ }
+ }
+ }
+
+ static IdmapDaemon getInstance() {
+ if (sInstance == null) {
+ sInstance = new IdmapDaemon();
+ }
+ return sInstance;
+ }
+
+ String createIdmap(String targetPath, String overlayPath, int policies, boolean enforce,
+ int userId) throws Exception {
+ try (Connection connection = connect()) {
+ return mService.createIdmap(targetPath, overlayPath, policies, enforce, userId);
+ }
+ }
+
+ boolean removeIdmap(String overlayPath, int userId) throws Exception {
+ try (Connection connection = connect()) {
+ return mService.removeIdmap(overlayPath, userId);
+ }
+ }
+
+ boolean verifyIdmap(String overlayPath, int policies, boolean enforce, int userId)
+ throws Exception {
+ try (Connection connection = connect()) {
+ return mService.verifyIdmap(overlayPath, policies, enforce, userId);
+ }
+ }
+
+ String getIdmapPath(String overlayPath, int userId) throws Exception {
+ try (Connection connection = connect()) {
+ return mService.getIdmapPath(overlayPath, userId);
+ }
+ }
+
+ static void startIdmapService() {
+ SystemProperties.set("ctl.start", IDMAP_DAEMON);
+ }
+
+ static void stopIdmapService() {
+ SystemProperties.set("ctl.stop", IDMAP_DAEMON);
+ }
+
+ private Connection connect() throws Exception {
+ synchronized (IDMAP_TOKEN) {
+ FgThread.getHandler().removeCallbacksAndMessages(IDMAP_TOKEN);
+ if (mService != null) {
+ // Not enough time has passed to stop the idmap service. Reuse the existing
+ // interface.
+ return new Connection();
+ }
+
+ // Start the idmap service if it is not currently running.
+ startIdmapService();
+
+ // Block until the service is found.
+ FutureTask<IBinder> bindIdmap = new FutureTask<>(() -> {
+ while (true) {
+ try {
+ IBinder binder = ServiceManager.getService(IDMAP_SERVICE);
+ if (binder != null) {
+ return binder;
+ }
+ } catch (Exception e) {
+ Slog.e(TAG, "service '" + IDMAP_SERVICE + "' not retrieved; "
+ + e.getMessage());
+ }
+ Thread.sleep(100);
+ }
+ });
+
+ IBinder binder;
+ try {
+ FgThread.getHandler().postAtFrontOfQueue(bindIdmap);
+ binder = bindIdmap.get(SERVICE_CONNECT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
+ } catch (Exception rethrow) {
+ Slog.e(TAG, "service '" + IDMAP_SERVICE + "' not found;");
+ throw rethrow;
+ }
+
+ try {
+ binder.linkToDeath(() -> {
+ Slog.w(TAG, "service '" + IDMAP_SERVICE + "' died");
+ }, 0);
+ } catch (RemoteException rethrow) {
+ Slog.e(TAG, "service '" + IDMAP_SERVICE + "' failed to be bound");
+ throw rethrow;
+ }
+
+ mService = IIdmap2.Stub.asInterface(binder);
+ if (DEBUG) {
+ Slog.d(TAG, "service '" + IDMAP_SERVICE + "' connected");
+ }
+
+ return new Connection();
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/om/IdmapManager.java b/services/core/java/com/android/server/om/IdmapManager.java
index 1f20968..288ef0e 100644
--- a/services/core/java/com/android/server/om/IdmapManager.java
+++ b/services/core/java/com/android/server/om/IdmapManager.java
@@ -16,9 +16,6 @@
package com.android.server.om;
-import static android.content.Context.IDMAP_SERVICE;
-import static android.text.format.DateUtils.SECOND_IN_MILLIS;
-
import static com.android.server.om.OverlayManagerService.DEBUG;
import static com.android.server.om.OverlayManagerService.TAG;
@@ -27,15 +24,11 @@
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.os.Build.VERSION_CODES;
-import android.os.IBinder;
import android.os.IIdmap2;
-import android.os.RemoteException;
-import android.os.ServiceManager;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.util.Slog;
-import com.android.internal.os.BackgroundThread;
import com.android.server.om.OverlayManagerServiceImpl.PackageManagerHelper;
import com.android.server.pm.Installer;
@@ -51,11 +44,6 @@
*/
class IdmapManager {
private static final boolean FEATURE_FLAG_IDMAP2 = true;
-
- private final Installer mInstaller;
- private final PackageManagerHelper mPackageManager;
- private IIdmap2 mIdmap2Service;
-
private static final boolean VENDOR_IS_Q_OR_LATER;
static {
final String value = SystemProperties.get("ro.vndk.version", "29");
@@ -70,12 +58,14 @@
VENDOR_IS_Q_OR_LATER = isQOrLater;
}
+ private final Installer mInstaller;
+ private final PackageManagerHelper mPackageManager;
+ private final IdmapDaemon mIdmapDaemon;
+
IdmapManager(final Installer installer, final PackageManagerHelper packageManager) {
mInstaller = installer;
mPackageManager = packageManager;
- if (FEATURE_FLAG_IDMAP2) {
- connectToIdmap2d();
- }
+ mIdmapDaemon = IdmapDaemon.getInstance();
}
boolean createIdmap(@NonNull final PackageInfo targetPackage,
@@ -91,11 +81,11 @@
if (FEATURE_FLAG_IDMAP2) {
int policies = calculateFulfilledPolicies(targetPackage, overlayPackage, userId);
boolean enforce = enforceOverlayable(overlayPackage);
- if (mIdmap2Service.verifyIdmap(overlayPath, policies, enforce, userId)) {
+ if (mIdmapDaemon.verifyIdmap(overlayPath, policies, enforce, userId)) {
return true;
}
- return mIdmap2Service.createIdmap(targetPath, overlayPath, policies, enforce,
- userId) != null;
+ return mIdmapDaemon.createIdmap(targetPath, overlayPath, policies,
+ enforce, userId) != null;
} else {
mInstaller.idmap(targetPath, overlayPath, sharedGid);
return true;
@@ -113,7 +103,7 @@
}
try {
if (FEATURE_FLAG_IDMAP2) {
- return mIdmap2Service.removeIdmap(oi.baseCodePath, userId);
+ return mIdmapDaemon.removeIdmap(oi.baseCodePath, userId);
} else {
mInstaller.removeIdmap(oi.baseCodePath);
return true;
@@ -137,7 +127,7 @@
final int userId) {
if (FEATURE_FLAG_IDMAP2) {
try {
- return mIdmap2Service.getIdmapPath(overlayPackagePath, userId);
+ return mIdmapDaemon.getIdmapPath(overlayPackagePath, userId);
} catch (Exception e) {
Slog.w(TAG, "failed to get idmap path for " + overlayPackagePath + ": "
+ e.getMessage());
@@ -151,35 +141,6 @@
}
}
- private void connectToIdmap2d() {
- IBinder binder = ServiceManager.getService(IDMAP_SERVICE);
- if (binder != null) {
- try {
- binder.linkToDeath(new IBinder.DeathRecipient() {
- @Override
- public void binderDied() {
- Slog.w(TAG, "service '" + IDMAP_SERVICE + "' died; reconnecting...");
- connectToIdmap2d();
- }
-
- }, 0);
- } catch (RemoteException e) {
- binder = null;
- }
- }
- if (binder != null) {
- mIdmap2Service = IIdmap2.Stub.asInterface(binder);
- if (DEBUG) {
- Slog.d(TAG, "service '" + IDMAP_SERVICE + "' connected");
- }
- } else {
- Slog.w(TAG, "service '" + IDMAP_SERVICE + "' not found; trying again...");
- BackgroundThread.getHandler().postDelayed(() -> {
- connectToIdmap2d();
- }, SECOND_IN_MILLIS);
- }
- }
-
/**
* Checks if overlayable and policies should be enforced on the specified overlay for backwards
* compatibility with pre-Q overlays.
diff --git a/services/core/java/com/android/server/om/OverlayManagerService.java b/services/core/java/com/android/server/om/OverlayManagerService.java
index da69986..ce95181 100644
--- a/services/core/java/com/android/server/om/OverlayManagerService.java
+++ b/services/core/java/com/android/server/om/OverlayManagerService.java
@@ -262,6 +262,7 @@
initIfNeeded();
onSwitchUser(UserHandle.USER_SYSTEM);
+ IdmapDaemon.stopIdmapService();
publishBinderService(Context.OVERLAY_SERVICE, mService);
publishLocalService(OverlayManagerService.class, this);
diff --git a/services/core/java/com/android/server/pm/ApexManager.java b/services/core/java/com/android/server/pm/ApexManager.java
index dd099b1..a1b6d49 100644
--- a/services/core/java/com/android/server/pm/ApexManager.java
+++ b/services/core/java/com/android/server/pm/ApexManager.java
@@ -282,30 +282,39 @@
if ((new File(ai.modulePath)).isDirectory()) {
break;
}
+ int flags = PackageManager.GET_META_DATA
+ | PackageManager.GET_SIGNING_CERTIFICATES
+ | PackageManager.GET_SIGNATURES;
+ PackageParser.Package pkg;
try {
- final PackageInfo pkg = PackageParser.generatePackageInfoFromApex(
- ai, PackageManager.GET_META_DATA
- | PackageManager.GET_SIGNING_CERTIFICATES);
- mAllPackagesCache.add(pkg);
- if (ai.isActive) {
- if (activePackagesSet.contains(pkg.packageName)) {
- throw new IllegalStateException(
- "Two active packages have the same name: "
- + pkg.packageName);
- }
- activePackagesSet.add(pkg.packageName);
- }
- if (ai.isFactory) {
- if (factoryPackagesSet.contains(pkg.packageName)) {
- throw new IllegalStateException(
- "Two factory packages have the same name: "
- + pkg.packageName);
- }
- factoryPackagesSet.add(pkg.packageName);
- }
+ File apexFile = new File(ai.modulePath);
+ PackageParser pp = new PackageParser();
+ pkg = pp.parsePackage(apexFile, flags, false);
+ PackageParser.collectCertificates(pkg, false);
} catch (PackageParser.PackageParserException pe) {
throw new IllegalStateException("Unable to parse: " + ai, pe);
}
+
+ final PackageInfo packageInfo =
+ PackageParser.generatePackageInfo(pkg, ai, flags);
+ mAllPackagesCache.add(packageInfo);
+ if (ai.isActive) {
+ if (activePackagesSet.contains(packageInfo.packageName)) {
+ throw new IllegalStateException(
+ "Two active packages have the same name: "
+ + packageInfo.packageName);
+ }
+ activePackagesSet.add(packageInfo.packageName);
+ }
+ if (ai.isFactory) {
+ if (factoryPackagesSet.contains(packageInfo.packageName)) {
+ throw new IllegalStateException(
+ "Two factory packages have the same name: "
+ + packageInfo.packageName);
+ }
+ factoryPackagesSet.add(packageInfo.packageName);
+ }
+
}
} catch (RemoteException re) {
Slog.e(TAG, "Unable to retrieve packages from apexservice: " + re.toString());
diff --git a/services/core/java/com/android/server/pm/AppsFilter.java b/services/core/java/com/android/server/pm/AppsFilter.java
index c87ab97..a189f7f 100644
--- a/services/core/java/com/android/server/pm/AppsFilter.java
+++ b/services/core/java/com/android/server/pm/AppsFilter.java
@@ -34,6 +34,7 @@
import android.util.SparseArray;
import com.android.internal.R;
+import com.android.server.FgThread;
import java.util.ArrayList;
import java.util.Collections;
@@ -42,6 +43,7 @@
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.concurrent.atomic.AtomicInteger;
/**
* The entity responsible for filtering visibility between apps based on declarations in their
@@ -50,6 +52,10 @@
class AppsFilter {
private static final String TAG = PackageManagerService.TAG;
+
+ // Forces filtering logic to run for debug purposes.
+ // STOPSHIP (b/136675067): should be false after development is complete
+ private static final boolean DEBUG_FILTERING = true;
/**
* This contains a list of packages that are implicitly queryable because another app explicitly
* interacted with it. For example, if application A starts a service in application B,
@@ -104,12 +110,11 @@
}
public static AppsFilter create(Context context) {
+ // tracks whether the feature is enabled where -1 is unknown, 0 is false and 1 is true;
+ final AtomicInteger featureEnabled = new AtomicInteger(-1);
+
final boolean forceSystemAppsQueryable =
context.getResources().getBoolean(R.bool.config_forceSystemPackagesQueryable);
- final ConfigProvider configProvider = () -> DeviceConfig.getBoolean(
- DeviceConfig.NAMESPACE_PACKAGE_MANAGER_SERVICE,
- "package_query_filtering_enabled",
- false);
final String[] forcedQueryablePackageNames;
if (forceSystemAppsQueryable) {
// all system apps already queryable, no need to read and parse individual exceptions
@@ -123,7 +128,19 @@
}
IPermissionManager permissionmgr =
(IPermissionManager) ServiceManager.getService("permissionmgr");
- return new AppsFilter(configProvider, permissionmgr,
+ return new AppsFilter(() -> {
+ if (featureEnabled.get() < 0) {
+ featureEnabled.set(DeviceConfig.getBoolean(
+ DeviceConfig.NAMESPACE_PACKAGE_MANAGER_SERVICE,
+ "package_query_filtering_enabled", false) ? 1 : 0);
+ DeviceConfig.addOnPropertiesChangedListener(
+ DeviceConfig.NAMESPACE_PACKAGE_MANAGER_SERVICE,
+ FgThread.getExecutor(),
+ pr -> featureEnabled.set(
+ pr.getBoolean("package_query_filtering_enabled", false) ? 1 : 0));
+ }
+ return featureEnabled.get() == 1;
+ }, permissionmgr,
context.getSystemService(AppOpsManager.class), forcedQueryablePackageNames,
forceSystemAppsQueryable);
}
@@ -260,6 +277,10 @@
if (callingUid < Process.FIRST_APPLICATION_UID) {
return false;
}
+ final boolean featureEnabled = mConfigProvider.isEnabled();
+ if (!featureEnabled && !DEBUG_FILTERING) {
+ return false;
+ }
if (callingSetting == null) {
Slog.wtf(TAG, "No setting found for non system uid " + callingUid);
return true;
@@ -277,7 +298,8 @@
final ArraySet<PackageSetting> packageSettings =
((SharedUserSetting) callingSetting).packages;
if (packageSettings != null && packageSettings.size() > 0) {
- for (PackageSetting packageSetting : packageSettings) {
+ for (int i = 0, max = packageSettings.size(); i < max; i++) {
+ final PackageSetting packageSetting = packageSettings.valueAt(i);
if (!shouldFilterApplicationInternal(packageSetting, targetPkgSetting,
userId)) {
// TODO: actually base this on a start / launch (not just a query)
@@ -288,13 +310,18 @@
callingPkgSetting = packageSetting;
}
}
+ if (callingPkgSetting == null) {
+ Slog.wtf(TAG, callingSetting + " does not have any non-null packages!");
+ return true;
+ }
} else {
+ Slog.wtf(TAG, callingSetting + " has no packages!");
return true;
}
}
- if (callingPkgSetting == null) {
- Slog.wtf(TAG, "What... " + callingSetting);
- return true;
+
+ if (!featureEnabled) {
+ return false;
}
final int mode = mAppOpsManager
.checkOpNoThrow(AppOpsManager.OP_QUERY_ALL_PACKAGES, callingUid,
@@ -303,7 +330,7 @@
case AppOpsManager.MODE_DEFAULT:
// if default, let's rely on remote feature toggle to determine whether to
// actually filter
- return mConfigProvider.isEnabled();
+ return true;
case AppOpsManager.MODE_ALLOWED:
// explicitly allowed to see all packages, don't filter
return false;
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 89ddc15..3f6d4df 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -10641,14 +10641,15 @@
final String realPkgName = request.realPkgName;
final List<String> changedAbiCodePath = result.changedAbiCodePath;
final PackageSetting pkgSetting;
+ if (request.pkgSetting != null && request.pkgSetting.sharedUser != null
+ && request.pkgSetting.sharedUser != result.pkgSetting.sharedUser) {
+ // shared user changed, remove from old shared user
+ request.pkgSetting.sharedUser.removePackage(request.pkgSetting);
+ }
if (result.existingSettingCopied) {
pkgSetting = request.pkgSetting;
pkgSetting.updateFrom(result.pkgSetting);
pkg.mExtras = pkgSetting;
- if (pkgSetting.sharedUser != null
- && pkgSetting.sharedUser.removePackage(result.pkgSetting)) {
- pkgSetting.sharedUser.addPackage(pkgSetting);
- }
} else {
pkgSetting = result.pkgSetting;
if (originalPkgSetting != null) {
@@ -10658,6 +10659,9 @@
mTransferedPackages.add(originalPkgSetting.name);
}
}
+ if (pkgSetting.sharedUser != null) {
+ pkgSetting.sharedUser.addPackage(pkgSetting);
+ }
// TODO(toddke): Consider a method specifically for modifying the Package object
// post scan; or, moving this stuff out of the Package object since it has nothing
// to do with the package on disk.
diff --git a/services/core/java/com/android/server/pm/StagingManager.java b/services/core/java/com/android/server/pm/StagingManager.java
index bdeaf02..6d3424c 100644
--- a/services/core/java/com/android/server/pm/StagingManager.java
+++ b/services/core/java/com/android/server/pm/StagingManager.java
@@ -160,25 +160,29 @@
final ApexInfoList apexInfoList = mApexManager.submitStagedSession(session.sessionId,
childSessionsIds.toArray());
final List<PackageInfo> result = new ArrayList<>();
- for (ApexInfo newPackage : apexInfoList.apexInfos) {
- final PackageInfo pkg;
+ for (ApexInfo apexInfo : apexInfoList.apexInfos) {
+ final PackageInfo packageInfo;
+ int flags = PackageManager.GET_META_DATA;
+ PackageParser.Package pkg;
try {
- pkg = PackageParser.generatePackageInfoFromApex(newPackage,
- PackageManager.GET_META_DATA);
+ File apexFile = new File(apexInfo.modulePath);
+ PackageParser pp = new PackageParser();
+ pkg = pp.parsePackage(apexFile, flags, false);
} catch (PackageParserException e) {
throw new PackageManagerException(SessionInfo.STAGED_SESSION_VERIFICATION_FAILED,
- "Failed to parse APEX package " + newPackage.modulePath, e);
+ "Failed to parse APEX package " + apexInfo.modulePath, e);
}
- final PackageInfo activePackage = mApexManager.getPackageInfo(pkg.packageName,
+ packageInfo = PackageParser.generatePackageInfo(pkg, apexInfo, flags);
+ final PackageInfo activePackage = mApexManager.getPackageInfo(packageInfo.packageName,
ApexManager.MATCH_ACTIVE_PACKAGE);
if (activePackage == null) {
- Slog.w(TAG, "Attempting to install new APEX package " + pkg.packageName);
+ Slog.w(TAG, "Attempting to install new APEX package " + packageInfo.packageName);
throw new PackageManagerException(SessionInfo.STAGED_SESSION_VERIFICATION_FAILED,
"It is forbidden to install new APEX packages.");
}
checkRequiredVersionCode(session, activePackage);
- checkDowngrade(session, activePackage, pkg);
- result.add(pkg);
+ checkDowngrade(session, activePackage, packageInfo);
+ result.add(packageInfo);
}
Slog.d(TAG, "Session " + session.sessionId + " has following APEX packages: ["
+ result.stream().map(p -> p.packageName).collect(Collectors.joining(",")) + "]");
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index a707aa8..2ccb6c1 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -75,6 +75,7 @@
import android.security.GateKeeper;
import android.service.gatekeeper.IGateKeeperService;
import android.stats.devicepolicy.DevicePolicyEnums;
+import android.util.ArraySet;
import android.util.AtomicFile;
import android.util.IntArray;
import android.util.Log;
@@ -125,6 +126,7 @@
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;
+import java.util.Set;
/**
* Service for {@link UserManager}.
@@ -214,7 +216,7 @@
@VisibleForTesting
static final int MAX_RECENTLY_REMOVED_IDS_SIZE = 100;
- private static final int USER_VERSION = 7;
+ private static final int USER_VERSION = 8;
private static final long EPOCH_PLUS_30_YEARS = 30L * 365 * 24 * 60 * 60 * 1000L; // ms
@@ -2139,6 +2141,7 @@
*/
@GuardedBy({"mRestrictionsLock", "mPackagesLock"})
private void upgradeIfNecessaryLP(Bundle oldGlobalUserRestrictions) {
+ Set<Integer> userIdsToWrite = new ArraySet<>();
final int originalVersion = mUserVersion;
int userVersion = mUserVersion;
if (userVersion < 1) {
@@ -2147,7 +2150,7 @@
if ("Primary".equals(userData.info.name)) {
userData.info.name =
mContext.getResources().getString(com.android.internal.R.string.owner_name);
- scheduleWriteUser(userData);
+ userIdsToWrite.add(userData.info.id);
}
userVersion = 1;
}
@@ -2157,7 +2160,7 @@
UserData userData = getUserDataNoChecks(UserHandle.USER_SYSTEM);
if ((userData.info.flags & UserInfo.FLAG_INITIALIZED) == 0) {
userData.info.flags |= UserInfo.FLAG_INITIALIZED;
- scheduleWriteUser(userData);
+ userIdsToWrite.add(userData.info.id);
}
userVersion = 2;
}
@@ -2182,7 +2185,7 @@
&& (userData.info.restrictedProfileParentId
== UserInfo.NO_PROFILE_GROUP_ID)) {
userData.info.restrictedProfileParentId = UserHandle.USER_SYSTEM;
- scheduleWriteUser(userData);
+ userIdsToWrite.add(userData.info.id);
}
}
}
@@ -2206,6 +2209,29 @@
userVersion = 7;
}
+ if (userVersion < 8) {
+ // Added FLAG_FULL and FLAG_SYSTEM flags.
+ synchronized (mUsersLock) {
+ UserData userData = mUsers.get(UserHandle.USER_SYSTEM);
+ userData.info.flags |= UserInfo.FLAG_SYSTEM;
+ if (!UserManager.isHeadlessSystemUserMode()) {
+ userData.info.flags |= UserInfo.FLAG_FULL;
+ }
+ userIdsToWrite.add(userData.info.id);
+
+ // Mark FULL all non-profile users except USER_SYSTEM.
+ // Start index at 1 since USER_SYSTEM is the smallest userId and we're skipping it.
+ for (int i = 1; i < mUsers.size(); i++) {
+ userData = mUsers.valueAt(i);
+ if ((userData.info.flags & UserInfo.FLAG_MANAGED_PROFILE) == 0) {
+ userData.info.flags |= UserInfo.FLAG_FULL;
+ userIdsToWrite.add(userData.info.id);
+ }
+ }
+ }
+ userVersion = 8;
+ }
+
if (userVersion < USER_VERSION) {
Slog.w(LOG_TAG, "User version " + mUserVersion + " didn't upgrade as expected to "
+ USER_VERSION);
@@ -2213,6 +2239,12 @@
mUserVersion = userVersion;
if (originalVersion < mUserVersion) {
+ for (int userId : userIdsToWrite) {
+ UserData userData = getUserDataNoChecks(userId);
+ if (userData != null) {
+ writeUserLP(userData);
+ }
+ }
writeUserListLP();
}
}
@@ -2220,12 +2252,15 @@
@GuardedBy({"mPackagesLock", "mRestrictionsLock"})
private void fallbackToSingleUserLP() {
- int flags = UserInfo.FLAG_INITIALIZED;
+ int flags = UserInfo.FLAG_SYSTEM | UserInfo.FLAG_INITIALIZED;
// In split system user mode, the admin and primary flags are assigned to the first human
// user.
if (!UserManager.isSplitSystemUser()) {
flags |= UserInfo.FLAG_ADMIN | UserInfo.FLAG_PRIMARY;
}
+ if (!UserManager.isHeadlessSystemUserMode()) {
+ flags |= UserInfo.FLAG_FULL;
+ }
// Create the system user
UserInfo system = new UserInfo(UserHandle.USER_SYSTEM, null, null, flags);
UserData userData = putUserInfo(system);
@@ -2262,14 +2297,14 @@
return mContext.getResources().getString(com.android.internal.R.string.owner_name);
}
- private void scheduleWriteUser(UserData UserData) {
+ private void scheduleWriteUser(UserData userData) {
if (DBG) {
debug("scheduleWriteUser");
}
// No need to wrap it within a lock -- worst case, we'll just post the same message
// twice.
- if (!mHandler.hasMessages(WRITE_USER_MSG, UserData)) {
- Message msg = mHandler.obtainMessage(WRITE_USER_MSG, UserData);
+ if (!mHandler.hasMessages(WRITE_USER_MSG, userData)) {
+ Message msg = mHandler.obtainMessage(WRITE_USER_MSG, userData);
mHandler.sendMessageDelayed(msg, WRITE_USER_DELAY);
}
}
@@ -2749,6 +2784,10 @@
}
}
}
+ if (!isManagedProfile) {
+ // New users cannot be system, and it's not a profile, so per-force it's FULL.
+ flags |= UserInfo.FLAG_FULL;
+ }
userId = getNextAvailableId();
Environment.getUserSystemDirectory(userId).mkdirs();
diff --git a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
index cfa370b..f0cf9cf 100644
--- a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
+++ b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
@@ -388,7 +388,7 @@
// Get a context for the caller to use to install the downgraded
// version of the package.
- Context context = null;
+ final Context context;
try {
context = mContext.createPackageContext(callerPackageName, 0);
} catch (PackageManager.NameNotFoundException e) {
@@ -434,7 +434,6 @@
}
int sessionId = packageInstaller.createSession(params);
PackageInstaller.Session session = packageInstaller.openSession(sessionId);
-
File[] packageCodePaths = RollbackStore.getPackageCodePaths(
data, info.getPackageName());
if (packageCodePaths == null) {
@@ -504,8 +503,10 @@
Intent broadcast = new Intent(Intent.ACTION_ROLLBACK_COMMITTED);
- mContext.sendBroadcastAsUser(broadcast, UserHandle.SYSTEM,
- Manifest.permission.MANAGE_ROLLBACKS);
+ for (UserInfo userInfo : UserManager.get(mContext).getUsers(true)) {
+ mContext.sendBroadcastAsUser(broadcast, userInfo.getUserHandle(),
+ Manifest.permission.MANAGE_ROLLBACKS);
+ }
});
}
);
diff --git a/services/core/java/com/android/server/tv/TvInputHardwareManager.java b/services/core/java/com/android/server/tv/TvInputHardwareManager.java
index f08e585..6ea274d 100755
--- a/services/core/java/com/android/server/tv/TvInputHardwareManager.java
+++ b/services/core/java/com/android/server/tv/TvInputHardwareManager.java
@@ -403,6 +403,10 @@
|| checkUidChangedLocked(connection, callingUid, resolvedUserId)) {
return;
}
+ ITvInputHardwareCallback callback = connection.getCallbackLocked();
+ if (callback != null) {
+ callback.asBinder().unlinkToDeath(connection, 0);
+ }
connection.resetLocked(null, null, null, null, null);
}
}
diff --git a/services/core/java/com/android/server/tv/TvRemoteProviderProxy.java b/services/core/java/com/android/server/tv/TvRemoteProviderProxy.java
index 557e9c8..b27d5ea 100644
--- a/services/core/java/com/android/server/tv/TvRemoteProviderProxy.java
+++ b/services/core/java/com/android/server/tv/TvRemoteProviderProxy.java
@@ -255,8 +255,6 @@
void clearInputBridge(TvRemoteProviderProxy provider, IBinder token);
- void sendTimeStamp(TvRemoteProviderProxy provider, IBinder token, long timestamp);
-
void sendKeyDown(TvRemoteProviderProxy provider, IBinder token, int keyCode);
void sendKeyUp(TvRemoteProviderProxy provider, IBinder token, int keyCode);
@@ -400,24 +398,8 @@
}
void sendTimestamp(final IBinder token, final long timestamp) {
- synchronized (mLock) {
- if (mActiveConnection == this && Binder.getCallingUid() == mUid) {
- final long idToken = Binder.clearCallingIdentity();
- try {
- if (mProviderMethods != null) {
- mProviderMethods.sendTimeStamp(TvRemoteProviderProxy.this, token,
- timestamp);
- }
- } finally {
- Binder.restoreCallingIdentity(idToken);
- }
- } else {
- if (DEBUG) {
- Slog.w(TAG,
- "sendTimeStamp, Invalid connection or incorrect uid: " + Binder
- .getCallingUid());
- }
- }
+ if (DEBUG) {
+ Slog.e(TAG, "sendTimestamp is deprecated, please remove all usages of this API.");
}
}
diff --git a/services/core/java/com/android/server/tv/TvRemoteService.java b/services/core/java/com/android/server/tv/TvRemoteService.java
index 961c992..4a41bf8 100644
--- a/services/core/java/com/android/server/tv/TvRemoteService.java
+++ b/services/core/java/com/android/server/tv/TvRemoteService.java
@@ -147,13 +147,6 @@
}
}
- private void sendTimeStampInternalLocked(IBinder token, long timestamp) {
- UinputBridge inputBridge = mBridgeMap.get(token);
- if (inputBridge != null) {
- inputBridge.sendTimestamp(token, timestamp);
- }
- }
-
private void sendKeyDownInternalLocked(IBinder token, int keyCode) {
if (DEBUG_KEYS) {
Slog.d(TAG, "sendKeyDownInternalLocked(), token: " + token + ", keyCode: " + keyCode);
@@ -298,15 +291,6 @@
}
@Override
- public void sendTimeStamp(TvRemoteProviderProxy provider, IBinder token, long timestamp) {
- synchronized (mLock) {
- if (mProviderList.contains(provider)) {
- mService.sendTimeStampInternalLocked(token, timestamp);
- }
- }
- }
-
- @Override
public void sendKeyDown(TvRemoteProviderProxy provider, IBinder token, int keyCode) {
if (DEBUG_KEYS) {
Slog.d(TAG, "sendKeyDown(), token: " + token + ", keyCode: " + keyCode);
diff --git a/services/core/java/com/android/server/tv/UinputBridge.java b/services/core/java/com/android/server/tv/UinputBridge.java
index 1a984f9..752aa66 100644
--- a/services/core/java/com/android/server/tv/UinputBridge.java
+++ b/services/core/java/com/android/server/tv/UinputBridge.java
@@ -16,13 +16,12 @@
package com.android.server.tv;
-import android.os.Binder;
import android.os.IBinder;
-import java.io.IOException;
-
import dalvik.system.CloseGuard;
+import java.io.IOException;
+
/**
* Sends the input event to the linux driver.
*/
@@ -35,7 +34,6 @@
int maxPointers);
private static native void nativeClose(long ptr);
private static native void nativeClear(long ptr);
- private static native void nativeSendTimestamp(long ptr, long timestamp);
private static native void nativeSendKey(long ptr, int keyCode, boolean down);
private static native void nativeSendPointerDown(long ptr, int pointerId, int x, int y);
private static native void nativeSendPointerUp(long ptr, int pointerId);
@@ -93,12 +91,6 @@
return mToken.equals(token);
}
- public void sendTimestamp(IBinder token, long timestamp) {
- if (isTokenValid(token)) {
- nativeSendTimestamp(mPtr, timestamp);
- }
- }
-
public void sendKeyDown(IBinder token, int keyCode) {
if (isTokenValid(token)) {
nativeSendKey(mPtr, keyCode, true /*down*/);
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index c8e806e..4135ef3 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -119,14 +119,12 @@
import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS;
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.CUSTOM_SCREEN_ROTATION;
import static com.android.server.wm.WindowManagerService.H.REPORT_FOCUS_CHANGE;
import static com.android.server.wm.WindowManagerService.H.REPORT_HARD_KEYBOARD_STATUS_CHANGE;
import static com.android.server.wm.WindowManagerService.H.REPORT_LOSING_FOCUS;
import static com.android.server.wm.WindowManagerService.H.UPDATE_DOCKED_STACK_DIVIDER;
import static com.android.server.wm.WindowManagerService.H.WINDOW_HIDE_TIMEOUT;
import static com.android.server.wm.WindowManagerService.LAYOUT_REPEAT_THRESHOLD;
-import static com.android.server.wm.WindowManagerService.MAX_ANIMATION_DURATION;
import static com.android.server.wm.WindowManagerService.SEAMLESS_ROTATION_TIMEOUT_DURATION;
import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_PLACING_SURFACES;
import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_REMOVING_FOCUS;
@@ -1534,13 +1532,8 @@
// NOTE: We disable the rotation in the emulator because
// it doesn't support hardware OpenGL emulation yet.
- if (CUSTOM_SCREEN_ROTATION && screenRotationAnimation != null
- && screenRotationAnimation.hasScreenshot()) {
- if (screenRotationAnimation.setRotation(getPendingTransaction(), rotation,
- MAX_ANIMATION_DURATION, mWmService.getTransitionAnimationScaleLocked(),
- mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight)) {
- mWmService.scheduleAnimationLocked();
- }
+ if (screenRotationAnimation != null && screenRotationAnimation.hasScreenshot()) {
+ screenRotationAnimation.setRotation(getPendingTransaction(), rotation);
}
forAllWindows(w -> {
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index a4476f0..e35ef25 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -2838,7 +2838,11 @@
mHandler.post(() -> {
final int displayId = getDisplayId();
getStatusBarManagerInternal().onDisplayReady(displayId);
- LocalServices.getService(WallpaperManagerInternal.class).onDisplayReady(displayId);
+ final WallpaperManagerInternal wpMgr = LocalServices
+ .getService(WallpaperManagerInternal.class);
+ if (wpMgr != null) {
+ wpMgr.onDisplayReady(displayId);
+ }
});
}
diff --git a/services/core/java/com/android/server/wm/KeyguardController.java b/services/core/java/com/android/server/wm/KeyguardController.java
index 85ba95f..422b6e5 100644
--- a/services/core/java/com/android/server/wm/KeyguardController.java
+++ b/services/core/java/com/android/server/wm/KeyguardController.java
@@ -90,11 +90,24 @@
}
/**
- * @return true if either 1) AOD is showing, or 2) Keyguard is showing, not going away, and not
- * being occluded on the given display, false otherwise.
+ * @return true if either Keyguard or AOD are showing, not going away, and not being occluded
+ * on the given display, false otherwise.
*/
boolean isKeyguardOrAodShowing(int displayId) {
- return mAodShowing || isKeyguardShowing(displayId);
+ return (mKeyguardShowing || mAodShowing) && !mKeyguardGoingAway
+ && !isDisplayOccluded(displayId);
+ }
+
+ /**
+ * @return {@code true} for default display when AOD is showing. Otherwise, same as
+ * {@link #isKeyguardOrAodShowing(int)}
+ * TODO(b/125198167): Replace isKeyguardOrAodShowing() by this logic.
+ */
+ boolean isKeyguardUnoccludedOrAodShowing(int displayId) {
+ if (displayId == DEFAULT_DISPLAY && mAodShowing) {
+ return true;
+ }
+ return isKeyguardOrAodShowing(displayId);
}
/**
@@ -102,7 +115,7 @@
* display, false otherwise
*/
boolean isKeyguardShowing(int displayId) {
- return mKeyguardShowing && !mKeyguardGoingAway && !isKeyguardOccluded(displayId);
+ return mKeyguardShowing && !mKeyguardGoingAway && !isDisplayOccluded(displayId);
}
/**
@@ -315,7 +328,7 @@
return;
}
- mWindowManager.onKeyguardOccludedChanged(isKeyguardOccluded(DEFAULT_DISPLAY));
+ mWindowManager.onKeyguardOccludedChanged(isDisplayOccluded(DEFAULT_DISPLAY));
if (isKeyguardLocked()) {
mWindowManager.deferSurfaceLayout();
try {
@@ -360,7 +373,7 @@
}
}
- private boolean isKeyguardOccluded(int displayId) {
+ private boolean isDisplayOccluded(int displayId) {
return getDisplay(displayId).mOccluded;
}
@@ -378,13 +391,13 @@
if (mBeforeUnoccludeTransit != TRANSIT_UNSET
&& dc.mAppTransition.getAppTransition() == TRANSIT_KEYGUARD_UNOCCLUDE
// TODO(b/113840485): Handle app transition for individual display.
- && isKeyguardOccluded(DEFAULT_DISPLAY)) {
+ && isDisplayOccluded(DEFAULT_DISPLAY)) {
// Reuse old transit in case we are occluding Keyguard again, meaning that we never
// actually occclude/unocclude Keyguard, but just run a normal transition.
return mBeforeUnoccludeTransit;
// TODO(b/113840485): Handle app transition for individual display.
- } else if (!isKeyguardOccluded(DEFAULT_DISPLAY)) {
+ } else if (!isDisplayOccluded(DEFAULT_DISPLAY)) {
// Save transit in case we dismiss/occlude Keyguard shortly after.
mBeforeUnoccludeTransit = dc.mAppTransition.getAppTransition();
@@ -396,7 +409,7 @@
private void dismissDockedStackIfNeeded() {
// TODO(b/113840485): Handle docked stack for individual display.
- if (mKeyguardShowing && isKeyguardOccluded(DEFAULT_DISPLAY)) {
+ if (mKeyguardShowing && isDisplayOccluded(DEFAULT_DISPLAY)) {
// The lock screen is currently showing, but is occluded by a window that can
// show on top of the lock screen. In this can we want to dismiss the docked
// stack since it will be complicated/risky to try to put the activity on top
@@ -421,9 +434,9 @@
private void updateKeyguardSleepToken(int displayId) {
final KeyguardDisplayState state = getDisplay(displayId);
- if (isKeyguardOrAodShowing(displayId) && state.mSleepToken == null) {
+ if (isKeyguardUnoccludedOrAodShowing(displayId) && state.mSleepToken == null) {
state.acquiredSleepToken();
- } else if (!isKeyguardOrAodShowing(displayId) && state.mSleepToken != null) {
+ } else if (!isKeyguardUnoccludedOrAodShowing(displayId) && state.mSleepToken != null) {
state.releaseSleepToken();
}
}
diff --git a/services/core/java/com/android/server/wm/RecentTasks.java b/services/core/java/com/android/server/wm/RecentTasks.java
index 541a8bb..fb6b5da 100644
--- a/services/core/java/com/android/server/wm/RecentTasks.java
+++ b/services/core/java/com/android/server/wm/RecentTasks.java
@@ -126,6 +126,7 @@
// iterating through the recents list
private static final ActivityInfo NO_ACTIVITY_INFO_TOKEN = new ActivityInfo();
private static final ApplicationInfo NO_APPLICATION_INFO_TOKEN = new ApplicationInfo();
+ private TaskChangeNotificationController mTaskNotificationController;
/**
* Callbacks made when manipulating the list.
@@ -228,6 +229,7 @@
mTaskPersister = taskPersister;
mGlobalMaxNumTasks = ActivityTaskManager.getMaxRecentTasksStatic();
mHasVisibleRecentTasks = true;
+ mTaskNotificationController = service.getTaskChangeNotificationController();
}
RecentTasks(ActivityTaskManagerService service, ActivityStackSupervisor stackSupervisor) {
@@ -238,6 +240,7 @@
mTaskPersister = new TaskPersister(systemDir, stackSupervisor, service, this,
stackSupervisor.mPersisterQueue);
mGlobalMaxNumTasks = ActivityTaskManager.getMaxRecentTasksStatic();
+ mTaskNotificationController = service.getTaskChangeNotificationController();
mHasVisibleRecentTasks = res.getBoolean(com.android.internal.R.bool.config_hasRecents);
loadParametersFromResources(res);
}
@@ -298,7 +301,7 @@
// Resume trimming tasks
trimInactiveRecentTasks();
- mService.getTaskChangeNotificationController().notifyTaskStackChanged();
+ mTaskNotificationController.notifyTaskStackChanged();
}
/**
@@ -427,12 +430,14 @@
for (int i = 0; i < mCallbacks.size(); i++) {
mCallbacks.get(i).onRecentTaskAdded(task);
}
+ mTaskNotificationController.notifyTaskListUpdated();
}
private void notifyTaskRemoved(TaskRecord task, boolean wasTrimmed, boolean killProcess) {
for (int i = 0; i < mCallbacks.size(); i++) {
mCallbacks.get(i).onRecentTaskRemoved(task, wasTrimmed, killProcess);
}
+ mTaskNotificationController.notifyTaskListUpdated();
}
/**
diff --git a/services/core/java/com/android/server/wm/RecentsAnimation.java b/services/core/java/com/android/server/wm/RecentsAnimation.java
index 036bef7..4f0332c 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimation.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimation.java
@@ -460,7 +460,7 @@
*/
static void notifyAnimationCancelBeforeStart(IRecentsAnimationRunner recentsAnimationRunner) {
try {
- recentsAnimationRunner.onAnimationCanceled(false /* deferredWithScreenshot */);
+ recentsAnimationRunner.onAnimationCanceled(null /* taskSnapshot */);
} catch (RemoteException e) {
Slog.e(TAG, "Failed to cancel recents animation before start", e);
}
diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java
index 6ea4d58..724a72e 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimationController.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java
@@ -23,8 +23,8 @@
import static android.view.RemoteAnimationTarget.MODE_OPENING;
import static android.view.WindowManager.DOCKED_INVALID;
import static android.view.WindowManager.INPUT_CONSUMER_RECENTS_ANIMATION;
-
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
+
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
import static com.android.server.wm.ActivityTaskManagerInternal.APP_TRANSITION_RECENTS_ANIM;
import static com.android.server.wm.AnimationAdapterProto.REMOTE;
@@ -525,18 +525,23 @@
// Screen shot previous task when next task starts transition and notify the runner.
// We will actually finish the animation once the runner calls cleanUpScreenshot().
final Task task = mPendingAnimations.get(0).mTask;
- screenshotRecentTask(task, reorderMode, runSynchronously);
+ final TaskSnapshot taskSnapshot = screenshotRecentTask(task, reorderMode,
+ runSynchronously);
try {
- mRunner.onAnimationCanceled(true /* deferredWithScreenshot */);
+ mRunner.onAnimationCanceled(taskSnapshot);
} catch (RemoteException e) {
Slog.e(TAG, "Failed to cancel recents animation", e);
}
+ if (taskSnapshot == null) {
+ mCallbacks.onAnimationFinished(reorderMode, runSynchronously,
+ false /* sendUserLeaveHint */);
+ }
} else {
// Otherwise, notify the runner and clean up the animation immediately
// Note: In the fallback case, this can trigger multiple onAnimationCancel() calls
// to the runner if we this actually triggers cancel twice on the caller
try {
- mRunner.onAnimationCanceled(false /* deferredWithScreenshot */);
+ mRunner.onAnimationCanceled(null /* taskSnapshot */);
} catch (RemoteException e) {
Slog.e(TAG, "Failed to cancel recents animation", e);
}
@@ -587,20 +592,32 @@
return mRequestDeferCancelUntilNextTransition && mCancelDeferredWithScreenshot;
}
- void screenshotRecentTask(Task task, @ReorderMode int reorderMode, boolean runSynchronously) {
- final TaskScreenshotAnimatable animatable = TaskScreenshotAnimatable.create(task);
- if (animatable != null) {
- mRecentScreenshotAnimator = new SurfaceAnimator(
- animatable,
- () -> {
- if (DEBUG_RECENTS_ANIMATIONS) {
- Slog.d(TAG, "mRecentScreenshotAnimator finish");
- }
- mCallbacks.onAnimationFinished(reorderMode, runSynchronously,
- false /* sendUserLeaveHint */);
- }, mService);
- mRecentScreenshotAnimator.transferAnimation(task.mSurfaceAnimator);
+ TaskSnapshot screenshotRecentTask(Task task, @ReorderMode int reorderMode,
+ boolean runSynchronously) {
+ final TaskSnapshotController snapshotController = mService.mTaskSnapshotController;
+ final ArraySet<Task> tasks = Sets.newArraySet(task);
+ snapshotController.snapshotTasks(tasks);
+ snapshotController.addSkipClosingAppSnapshotTasks(tasks);
+ final TaskSnapshot taskSnapshot = snapshotController.getSnapshot(task.mTaskId,
+ task.mUserId, false /* restoreFromDisk */, false /* reducedResolution */);
+ if (taskSnapshot == null) {
+ return null;
}
+
+ final TaskScreenshotAnimatable animatable = new TaskScreenshotAnimatable(task,
+ new SurfaceControl.ScreenshotGraphicBuffer(taskSnapshot.getSnapshot(),
+ taskSnapshot.getColorSpace(), false /* containsSecureLayers */));
+ mRecentScreenshotAnimator = new SurfaceAnimator(
+ animatable,
+ () -> {
+ if (DEBUG_RECENTS_ANIMATIONS) {
+ Slog.d(TAG, "mRecentScreenshotAnimator finish");
+ }
+ mCallbacks.onAnimationFinished(reorderMode, runSynchronously,
+ false /* sendUserLeaveHint */);
+ }, mService);
+ mRecentScreenshotAnimator.transferAnimation(task.mSurfaceAnimator);
+ return taskSnapshot;
}
void cleanupAnimation(@ReorderMode int reorderMode) {
diff --git a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
index cb15f57..82dde0d 100644
--- a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
+++ b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
@@ -286,20 +286,11 @@
setSnapshotTransform(t, mSnapshotInitialMatrix, 1.0f);
}
- public boolean setRotation(SurfaceControl.Transaction t, int rotation,
- long maxAnimationDuration, float animationScale, int finalWidth, int finalHeight) {
- setRotation(t, rotation);
-
- // Don't start animation yet.
- return false;
- }
-
/**
* Returns true if animating.
*/
private boolean startAnimation(SurfaceControl.Transaction t, long maxAnimationDuration,
- float animationScale, int finalWidth, int finalHeight, boolean dismissing,
- int exitAnim, int enterAnim) {
+ float animationScale, int finalWidth, int finalHeight, int exitAnim, int enterAnim) {
if (mSurfaceControl == null) {
// Can't do animation.
return false;
@@ -420,7 +411,7 @@
}
if (!mStarted) {
startAnimation(t, maxAnimationDuration, animationScale, finalWidth, finalHeight,
- true, exitAnim, enterAnim);
+ exitAnim, enterAnim);
}
if (!mStarted) {
return false;
diff --git a/services/core/java/com/android/server/wm/TaskChangeNotificationController.java b/services/core/java/com/android/server/wm/TaskChangeNotificationController.java
index f776062..c2c4767 100644
--- a/services/core/java/com/android/server/wm/TaskChangeNotificationController.java
+++ b/services/core/java/com/android/server/wm/TaskChangeNotificationController.java
@@ -56,6 +56,7 @@
private static final int NOTIFY_BACK_PRESSED_ON_TASK_ROOT = 21;
private static final int NOTIFY_SINGLE_TASK_DISPLAY_DRAWN = 22;
private static final int NOTIFY_TASK_DISPLAY_CHANGED_LISTENERS_MSG = 23;
+ private static final int NOTIFY_TASK_LIST_UPDATED_LISTENERS_MSG = 24;
// Delay in notifying task stack change listeners (in millis)
private static final int NOTIFY_TASK_STACK_CHANGE_LISTENERS_DELAY = 100;
@@ -164,6 +165,10 @@
l.onTaskDisplayChanged(m.arg1, m.arg2);
};
+ private final TaskStackConsumer mNotifyTaskListUpdated = (l, m) -> {
+ l.onRecentTaskListUpdated();
+ };
+
@FunctionalInterface
public interface TaskStackConsumer {
void accept(ITaskStackListener t, Message m) throws RemoteException;
@@ -249,6 +254,9 @@
case NOTIFY_TASK_DISPLAY_CHANGED_LISTENERS_MSG:
forAllRemoteListeners(mNotifyTaskDisplayChanged, msg);
break;
+ case NOTIFY_TASK_LIST_UPDATED_LISTENERS_MSG:
+ forAllRemoteListeners(mNotifyTaskListUpdated, msg);
+ break;
}
}
}
@@ -513,4 +521,13 @@
forAllLocalListeners(mNotifyTaskStackChanged, msg);
msg.sendToTarget();
}
+
+ /**
+ * Called when any additions or deletions to the recent tasks list have been made.
+ */
+ void notifyTaskListUpdated() {
+ final Message msg = mHandler.obtainMessage(NOTIFY_TASK_LIST_UPDATED_LISTENERS_MSG);
+ forAllLocalListeners(mNotifyTaskListUpdated, msg);
+ msg.sendToTarget();
+ }
}
diff --git a/services/core/java/com/android/server/wm/TaskScreenshotAnimatable.java b/services/core/java/com/android/server/wm/TaskScreenshotAnimatable.java
index 143543e..d6c2f66 100644
--- a/services/core/java/com/android/server/wm/TaskScreenshotAnimatable.java
+++ b/services/core/java/com/android/server/wm/TaskScreenshotAnimatable.java
@@ -18,7 +18,6 @@
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_RECENTS_ANIMATIONS;
import android.graphics.GraphicBuffer;
-import android.graphics.Rect;
import android.util.Slog;
import android.view.Surface;
import android.view.SurfaceControl;
@@ -37,20 +36,7 @@
private int mWidth;
private int mHeight;
- public static TaskScreenshotAnimatable create(Task task) {
- return new TaskScreenshotAnimatable(task, getBufferFromTask(task));
- }
-
- private static SurfaceControl.ScreenshotGraphicBuffer getBufferFromTask(Task task) {
- if (task == null) {
- return null;
- }
- final Rect tmpRect = task.getBounds();
- tmpRect.offset(0, 0);
- return SurfaceControl.captureLayers(task.getSurfaceControl(), tmpRect, 1f);
- }
-
- private TaskScreenshotAnimatable(Task task,
+ TaskScreenshotAnimatable(Task task,
SurfaceControl.ScreenshotGraphicBuffer screenshotBuffer) {
GraphicBuffer buffer = screenshotBuffer == null
? null : screenshotBuffer.getGraphicBuffer();
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 3221aef..86faad0 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -336,11 +336,6 @@
/** Amount of time to allow a last ANR message to exist before freeing the memory. */
static final int LAST_ANR_LIFETIME_DURATION_MSECS = 2 * 60 * 60 * 1000; // Two hours
- /**
- * If true, the window manager will do its own custom freezing and general
- * management of the screen during rotation.
- */
- static final boolean CUSTOM_SCREEN_ROTATION = true;
// Maximum number of milliseconds to wait for input devices to be enumerated before
// proceding with safe mode detection.
@@ -5395,25 +5390,23 @@
}
mLatencyTracker.onActionStart(ACTION_ROTATE_SCREEN);
- if (CUSTOM_SCREEN_ROTATION) {
- mExitAnimId = exitAnim;
- mEnterAnimId = enterAnim;
- ScreenRotationAnimation screenRotationAnimation =
- mAnimator.getScreenRotationAnimationLocked(mFrozenDisplayId);
- if (screenRotationAnimation != null) {
- screenRotationAnimation.kill();
- }
-
- // Check whether the current screen contains any secure content.
- boolean isSecure = displayContent.hasSecureWindowOnScreen();
-
- displayContent.updateDisplayInfo();
- screenRotationAnimation = new ScreenRotationAnimation(mContext, displayContent,
- displayContent.getDisplayRotation().isFixedToUserRotation(), isSecure,
- this);
- mAnimator.setScreenRotationAnimationLocked(mFrozenDisplayId,
- screenRotationAnimation);
+ mExitAnimId = exitAnim;
+ mEnterAnimId = enterAnim;
+ ScreenRotationAnimation screenRotationAnimation =
+ mAnimator.getScreenRotationAnimationLocked(mFrozenDisplayId);
+ if (screenRotationAnimation != null) {
+ screenRotationAnimation.kill();
}
+
+ // Check whether the current screen contains any secure content.
+ boolean isSecure = displayContent.hasSecureWindowOnScreen();
+
+ displayContent.updateDisplayInfo();
+ screenRotationAnimation = new ScreenRotationAnimation(mContext, displayContent,
+ displayContent.getDisplayRotation().isFixedToUserRotation(), isSecure,
+ this);
+ mAnimator.setScreenRotationAnimationLocked(mFrozenDisplayId,
+ screenRotationAnimation);
}
void stopFreezingDisplayLocked() {
@@ -5466,8 +5459,7 @@
ScreenRotationAnimation screenRotationAnimation =
mAnimator.getScreenRotationAnimationLocked(displayId);
- if (CUSTOM_SCREEN_ROTATION && screenRotationAnimation != null
- && screenRotationAnimation.hasScreenshot()) {
+ if (screenRotationAnimation != null && screenRotationAnimation.hasScreenshot()) {
if (DEBUG_ORIENTATION) Slog.i(TAG_WM, "**** Dismissing screen rotation animation");
DisplayInfo displayInfo = displayContent.getDisplayInfo();
// Get rotation animation again, with new top window
@@ -5511,7 +5503,7 @@
mScreenFrozenLock.release();
- if (updateRotation && displayContent != null && updateRotation) {
+ if (updateRotation && displayContent != null) {
if (DEBUG_ORIENTATION) Slog.d(TAG_WM, "Performing post-rotate rotation");
configChanged |= displayContent.updateRotationUnchecked();
}
diff --git a/services/core/jni/com_android_server_tv_TvUinputBridge.cpp b/services/core/jni/com_android_server_tv_TvUinputBridge.cpp
index 980922a..c832c18 100644
--- a/services/core/jni/com_android_server_tv_TvUinputBridge.cpp
+++ b/services/core/jni/com_android_server_tv_TvUinputBridge.cpp
@@ -43,10 +43,6 @@
#include <sys/stat.h>
#include <sys/types.h>
-// Refer to EventHub.h
-#define MSC_ANDROID_TIME_SEC 0x6
-#define MSC_ANDROID_TIME_USEC 0x7
-
#define SLOT_UNKNOWN -1
namespace android {
@@ -153,11 +149,6 @@
ioctl(fd, UI_SET_KEYBIT, KEYS[i].linuxKeyCode);
}
- // set the misc events maps
- ioctl(fd, UI_SET_EVBIT, EV_MSC);
- ioctl(fd, UI_SET_MSCBIT, MSC_ANDROID_TIME_SEC);
- ioctl(fd, UI_SET_MSCBIT, MSC_ANDROID_TIME_USEC);
-
// register the input device
if (write(fd, &uinp, sizeof(uinp)) != sizeof(uinp)) {
ALOGE("Cannot write uinput_user_dev to fd %d: %s.", fd, strerror(errno));
@@ -200,13 +191,6 @@
delete connection;
}
-static void nativeSendTimestamp(JNIEnv* env, jclass clazz, jlong ptr, jlong timestamp) {
- NativeConnection* connection = reinterpret_cast<NativeConnection*>(ptr);
-
- connection->sendEvent(EV_MSC, MSC_ANDROID_TIME_SEC, timestamp / 1000L);
- connection->sendEvent(EV_MSC, MSC_ANDROID_TIME_USEC, (timestamp % 1000L) * 1000L);
-}
-
static void nativeSendKey(JNIEnv* env, jclass clazz, jlong ptr, jint keyCode, jboolean down) {
int32_t code = getLinuxKeyCode(keyCode);
NativeConnection* connection = reinterpret_cast<NativeConnection*>(ptr);
@@ -281,8 +265,6 @@
(void*)nativeOpen },
{ "nativeClose", "(J)V",
(void*)nativeClose },
- { "nativeSendTimestamp", "(JJ)V",
- (void*)nativeSendTimestamp },
{ "nativeSendKey", "(JIZ)V",
(void*)nativeSendKey },
{ "nativeSendPointerDown", "(JIII)V",
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 6e0d834..83b3194 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -1476,6 +1476,8 @@
t.traceBegin("StartWallpaperManagerService");
mSystemServiceManager.startService(WALLPAPER_SERVICE_CLASS);
t.traceEnd();
+ } else {
+ Slog.i(TAG, "Wallpaper service disabled by config");
}
t.traceBegin("StartAudioService");
diff --git a/services/net/java/android/net/dhcp/DhcpServerCallbacks.java b/services/net/java/android/net/dhcp/DhcpServerCallbacks.java
index bb56876..7c413779 100644
--- a/services/net/java/android/net/dhcp/DhcpServerCallbacks.java
+++ b/services/net/java/android/net/dhcp/DhcpServerCallbacks.java
@@ -21,13 +21,11 @@
* @hide
*/
public abstract class DhcpServerCallbacks extends IDhcpServerCallbacks.Stub {
- // TODO: add @Override here once the API is versioned
-
/**
* Get the version of the aidl interface implemented by the callbacks.
*/
+ @Override
public int getInterfaceVersion() {
- // TODO: return IDhcpServerCallbacks.VERSION;
- return 0;
+ return IDhcpServerCallbacks.VERSION;
}
}
diff --git a/services/robotests/backup/src/com/android/server/backup/BackupManagerServiceTest.java b/services/robotests/backup/src/com/android/server/backup/BackupManagerServiceTest.java
index e55c4a6..0d99561 100644
--- a/services/robotests/backup/src/com/android/server/backup/BackupManagerServiceTest.java
+++ b/services/robotests/backup/src/com/android/server/backup/BackupManagerServiceTest.java
@@ -36,6 +36,8 @@
import static org.robolectric.Shadows.shadowOf;
import static org.testng.Assert.expectThrows;
+import static java.util.Collections.emptySet;
+
import android.annotation.UserIdInt;
import android.app.Application;
import android.app.backup.IBackupManagerMonitor;
@@ -53,6 +55,7 @@
import com.android.server.backup.testing.TransportData;
import com.android.server.testing.shadows.ShadowApplicationPackageManager;
import com.android.server.testing.shadows.ShadowBinder;
+import com.android.server.testing.shadows.ShadowSystemServiceRegistry;
import org.junit.After;
import org.junit.Before;
@@ -73,7 +76,12 @@
/** Tests for the user-aware backup/restore system service {@link BackupManagerService}. */
@RunWith(RobolectricTestRunner.class)
-@Config(shadows = {ShadowApplicationPackageManager.class, ShadowBinder.class})
+@Config(
+ shadows = {
+ ShadowApplicationPackageManager.class,
+ ShadowBinder.class,
+ ShadowSystemServiceRegistry.class
+ })
@Presubmit
public class BackupManagerServiceTest {
private static final String TEST_PACKAGE = "package";
@@ -154,7 +162,7 @@
public void testStartServiceForUser_registersUser() throws Exception {
BackupManagerService backupManagerService = createService();
- backupManagerService.startServiceForUser(mUserOneId);
+ backupManagerService.startServiceForUser(mUserOneId, emptySet());
SparseArray<UserBackupManagerService> serviceUsers = backupManagerService.getUserServices();
assertThat(serviceUsers.size()).isEqualTo(1);
diff --git a/services/robotests/backup/src/com/android/server/backup/FullBackupJobTest.java b/services/robotests/backup/src/com/android/server/backup/FullBackupJobTest.java
index 9a78d0b3..dbc0da7 100644
--- a/services/robotests/backup/src/com/android/server/backup/FullBackupJobTest.java
+++ b/services/robotests/backup/src/com/android/server/backup/FullBackupJobTest.java
@@ -25,6 +25,8 @@
import android.os.UserHandle;
import android.platform.test.annotations.Presubmit;
+import com.android.server.testing.shadows.ShadowSystemServiceRegistry;
+
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@@ -36,7 +38,7 @@
import org.robolectric.shadows.ShadowJobScheduler;
@RunWith(RobolectricTestRunner.class)
-@Config(shadows = {ShadowJobScheduler.class})
+@Config(shadows = {ShadowJobScheduler.class, ShadowSystemServiceRegistry.class})
@Presubmit
public class FullBackupJobTest {
private Context mContext;
diff --git a/services/robotests/backup/src/com/android/server/backup/KeyValueBackupJobTest.java b/services/robotests/backup/src/com/android/server/backup/KeyValueBackupJobTest.java
index 8d9e44f..1c5fac2 100644
--- a/services/robotests/backup/src/com/android/server/backup/KeyValueBackupJobTest.java
+++ b/services/robotests/backup/src/com/android/server/backup/KeyValueBackupJobTest.java
@@ -24,14 +24,18 @@
import android.os.UserHandle;
import android.platform.test.annotations.Presubmit;
+import com.android.server.testing.shadows.ShadowSystemServiceRegistry;
+
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
@RunWith(RobolectricTestRunner.class)
+@Config(shadows = {ShadowSystemServiceRegistry.class})
@Presubmit
public class KeyValueBackupJobTest {
private Context mContext;
diff --git a/services/robotests/backup/src/com/android/server/backup/UserBackupManagerServiceTest.java b/services/robotests/backup/src/com/android/server/backup/UserBackupManagerServiceTest.java
index 74fe81c..84e810d 100644
--- a/services/robotests/backup/src/com/android/server/backup/UserBackupManagerServiceTest.java
+++ b/services/robotests/backup/src/com/android/server/backup/UserBackupManagerServiceTest.java
@@ -63,6 +63,7 @@
import com.android.server.testing.shadows.ShadowBinder;
import com.android.server.testing.shadows.ShadowKeyValueBackupJob;
import com.android.server.testing.shadows.ShadowKeyValueBackupTask;
+import com.android.server.testing.shadows.ShadowSystemServiceRegistry;
import org.junit.After;
import org.junit.Before;
@@ -88,7 +89,12 @@
* UserBackupManagerService} that performs operations for its target user.
*/
@RunWith(RobolectricTestRunner.class)
-@Config(shadows = {ShadowAppBackupUtils.class, ShadowApplicationPackageManager.class})
+@Config(
+ shadows = {
+ ShadowAppBackupUtils.class,
+ ShadowApplicationPackageManager.class,
+ ShadowSystemServiceRegistry.class
+ })
@Presubmit
public class UserBackupManagerServiceTest {
private static final String TAG = "BMSTest";
diff --git a/services/robotests/backup/src/com/android/server/backup/internal/SetupObserverTest.java b/services/robotests/backup/src/com/android/server/backup/internal/SetupObserverTest.java
index 44e9e6a..e49425b 100644
--- a/services/robotests/backup/src/com/android/server/backup/internal/SetupObserverTest.java
+++ b/services/robotests/backup/src/com/android/server/backup/internal/SetupObserverTest.java
@@ -32,6 +32,7 @@
import com.android.server.backup.UserBackupManagerService;
import com.android.server.backup.testing.BackupManagerServiceTestUtils;
import com.android.server.testing.shadows.ShadowApplicationPackageManager;
+import com.android.server.testing.shadows.ShadowSystemServiceRegistry;
import org.junit.Before;
import org.junit.Test;
@@ -51,7 +52,12 @@
* UserBackupManagerService}.
*/
@RunWith(RobolectricTestRunner.class)
-@Config(shadows = {ShadowApplicationPackageManager.class, ShadowJobScheduler.class})
+@Config(
+ shadows = {
+ ShadowApplicationPackageManager.class,
+ ShadowJobScheduler.class,
+ ShadowSystemServiceRegistry.class
+ })
@Presubmit
public class SetupObserverTest {
private static final String TAG = "SetupObserverTest";
diff --git a/services/robotests/backup/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java b/services/robotests/backup/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java
index 43691e0..6a90d0b 100644
--- a/services/robotests/backup/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java
+++ b/services/robotests/backup/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java
@@ -94,7 +94,6 @@
import android.os.Looper;
import android.os.Message;
import android.os.ParcelFileDescriptor;
-import android.os.PowerManager;
import android.os.RemoteException;
import android.platform.test.annotations.Presubmit;
import android.util.Pair;
@@ -121,6 +120,7 @@
import com.android.server.testing.shadows.ShadowBackupDataInput;
import com.android.server.testing.shadows.ShadowBackupDataOutput;
import com.android.server.testing.shadows.ShadowEventLog;
+import com.android.server.testing.shadows.ShadowSystemServiceRegistry;
import com.google.common.truth.IterableSubject;
@@ -164,10 +164,11 @@
ShadowBackupDataInput.class,
ShadowBackupDataOutput.class,
ShadowEventLog.class,
- ShadowQueuedWork.class
+ ShadowQueuedWork.class,
+ ShadowSystemServiceRegistry.class
})
@Presubmit
-public class KeyValueBackupTaskTest {
+public class KeyValueBackupTaskTest {
private static final PackageData PACKAGE_1 = keyValuePackage(1);
private static final PackageData PACKAGE_2 = keyValuePackage(2);
private static final String BACKUP_AGENT_SHARED_PREFS_SYNCHRONIZER_CLASS =
@@ -184,7 +185,7 @@
private TransportData mTransport;
private ShadowLooper mShadowBackupLooper;
private Handler mBackupHandler;
- private PowerManager.WakeLock mWakeLock;
+ private UserBackupManagerService.BackupWakeLock mWakeLock;
private KeyValueBackupReporter mReporter;
private PackageManager mPackageManager;
private ShadowPackageManager mShadowPackageManager;
diff --git a/services/robotests/backup/src/com/android/server/backup/restore/ActiveRestoreSessionTest.java b/services/robotests/backup/src/com/android/server/backup/restore/ActiveRestoreSessionTest.java
index f4cea7a..3fc421d 100644
--- a/services/robotests/backup/src/com/android/server/backup/restore/ActiveRestoreSessionTest.java
+++ b/services/robotests/backup/src/com/android/server/backup/restore/ActiveRestoreSessionTest.java
@@ -18,7 +18,7 @@
import static com.android.server.backup.testing.BackupManagerServiceTestUtils.createBackupWakeLock;
import static com.android.server.backup.testing.BackupManagerServiceTestUtils.setUpBackupManagerServiceBasics;
-import static com.android.server.backup.testing.BackupManagerServiceTestUtils.startBackupThreadAndGetLooper;
+import static com.android.server.backup.testing.BackupManagerServiceTestUtils.startBackupThread;
import static com.android.server.backup.testing.TestUtils.assertEventLogged;
import static com.android.server.backup.testing.TestUtils.assertEventNotLogged;
import static com.android.server.backup.testing.TransportData.backupTransport;
@@ -44,8 +44,8 @@
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.os.Handler;
+import android.os.HandlerThread;
import android.os.Looper;
-import android.os.PowerManager;
import android.os.RemoteException;
import android.platform.test.annotations.Presubmit;
@@ -98,7 +98,7 @@
@Mock private IBackupManagerMonitor mMonitor;
private ShadowLooper mShadowBackupLooper;
private ShadowApplication mShadowApplication;
- private PowerManager.WakeLock mWakeLock;
+ private UserBackupManagerService.BackupWakeLock mWakeLock;
private TransportData mTransport;
private RestoreSet mRestoreSet1;
private RestoreSet mRestoreSet2;
@@ -118,7 +118,8 @@
mShadowPackageManager = shadowOf(application.getPackageManager());
- Looper backupLooper = startBackupThreadAndGetLooper();
+ HandlerThread handlerThread = startBackupThread(null);
+ Looper backupLooper = handlerThread.getLooper();
mShadowBackupLooper = shadowOf(backupLooper);
Handler mainHandler = new Handler(Looper.getMainLooper());
@@ -129,7 +130,7 @@
// We need to mock BMS timeout parameters before initializing the BackupHandler since
// the constructor of BackupHandler relies on it.
when(mBackupManagerService.getAgentTimeoutParameters()).thenReturn(agentTimeoutParameters);
- BackupHandler backupHandler = new BackupHandler(mBackupManagerService, backupLooper);
+ BackupHandler backupHandler = new BackupHandler(mBackupManagerService, handlerThread);
mWakeLock = createBackupWakeLock(application);
diff --git a/services/robotests/backup/src/com/android/server/backup/testing/BackupManagerServiceTestUtils.java b/services/robotests/backup/src/com/android/server/backup/testing/BackupManagerServiceTestUtils.java
index 47abcc5..392d182 100644
--- a/services/robotests/backup/src/com/android/server/backup/testing/BackupManagerServiceTestUtils.java
+++ b/services/robotests/backup/src/com/android/server/backup/testing/BackupManagerServiceTestUtils.java
@@ -113,7 +113,7 @@
TransportManager transportManager,
PackageManager packageManager,
Handler backupHandler,
- PowerManager.WakeLock wakeLock,
+ UserBackupManagerService.BackupWakeLock wakeLock,
BackupAgentTimeoutParameters agentTimeoutParameters) {
when(backupManagerService.getContext()).thenReturn(application);
@@ -161,10 +161,12 @@
});
}
- public static PowerManager.WakeLock createBackupWakeLock(Application application) {
+ public static UserBackupManagerService.BackupWakeLock createBackupWakeLock(
+ Application application) {
PowerManager powerManager =
(PowerManager) application.getSystemService(Context.POWER_SERVICE);
- return powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "*backup*");
+ return new UserBackupManagerService.BackupWakeLock(
+ powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "*backup*"));
}
/**
diff --git a/services/robotests/src/com/android/server/testing/shadows/ShadowSystemServiceRegistry.java b/services/robotests/src/com/android/server/testing/shadows/ShadowSystemServiceRegistry.java
new file mode 100644
index 0000000..c59798fc92
--- /dev/null
+++ b/services/robotests/src/com/android/server/testing/shadows/ShadowSystemServiceRegistry.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.server.testing.shadows;
+
+import android.app.SystemServiceRegistry;
+import android.app.job.JobSchedulerFrameworkInitializer;
+
+import org.robolectric.annotation.Implementation;
+import org.robolectric.annotation.Implements;
+import org.robolectric.util.ReflectionHelpers;
+
+/**
+ * Shadow of {@link SystemServiceRegistry}
+ *
+ * <p>JobSchedulerFrameworkInitializer contains a static initializer registering JobScheduler as a
+ * system service. We need to make sure the initializer is run before the tests that use
+ * JobScheduler. And we're putting this on the static initializer of SystemServiceRegistry since
+ * other services are registered here.
+ */
+@Implements(className = "android.app.SystemServiceRegistry")
+public class ShadowSystemServiceRegistry {
+ @Implementation
+ protected static void __staticInitializer__() {
+ // Make sure the static init in the real class is still executed.
+ ReflectionHelpers.callStaticMethod(SystemServiceRegistry.class, "__staticInitializer__");
+ try {
+ Class.forName(JobSchedulerFrameworkInitializer.class.getCanonicalName());
+ } catch (ClassNotFoundException e) {
+ // Rethrowing as an unchecked exception because checked exceptions are not allowed in
+ // static blocks.
+ throw new ExceptionInInitializerError(e);
+ }
+ }
+}
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/AppCompactorTest.java b/services/tests/mockingservicestests/src/com/android/server/am/AppCompactorTest.java
index 101bee2..48e459f 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/AppCompactorTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/AppCompactorTest.java
@@ -82,7 +82,9 @@
true /* allowIo */);
mThread.start();
- ActivityManagerService ams = new ActivityManagerService(new TestInjector(), mThread);
+ ActivityManagerService ams = new ActivityManagerService(
+ new TestInjector(InstrumentationRegistry.getInstrumentation().getContext()),
+ mThread);
mCompactorUnderTest = new AppCompactor(ams,
new AppCompactor.PropertyChangedCallbackForTest() {
@Override
@@ -660,6 +662,11 @@
}
private class TestInjector extends Injector {
+
+ TestInjector(Context context) {
+ super(context);
+ }
+
@Override
public AppOpsService getAppOpsService(File file, Handler handler) {
return mAppOpsService;
@@ -669,10 +676,5 @@
public Handler getUiHandler(ActivityManagerService service) {
return mHandler;
}
-
- @Override
- public Context getContext() {
- return InstrumentationRegistry.getInstrumentation().getContext();
- }
}
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
new file mode 100644
index 0000000..9670899
--- /dev/null
+++ b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
@@ -0,0 +1,1615 @@
+/*
+ * 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 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;
+import static android.app.ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT;
+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;
+import static android.app.ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND;
+import static android.app.ActivityManager.PROCESS_STATE_LAST_ACTIVITY;
+import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT;
+import static android.app.ActivityManager.PROCESS_STATE_PERSISTENT_UI;
+import static android.app.ActivityManager.PROCESS_STATE_RECEIVER;
+import static android.app.ActivityManager.PROCESS_STATE_SERVICE;
+import static android.app.ActivityManager.PROCESS_STATE_TOP;
+import static android.app.ActivityManager.PROCESS_STATE_TOP_SLEEPING;
+import static android.app.ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND;
+
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+
+import static com.android.server.am.ProcessList.BACKUP_APP_ADJ;
+import static com.android.server.am.ProcessList.CACHED_APP_MAX_ADJ;
+import static com.android.server.am.ProcessList.CACHED_APP_MIN_ADJ;
+import static com.android.server.am.ProcessList.FOREGROUND_APP_ADJ;
+import static com.android.server.am.ProcessList.HEAVY_WEIGHT_APP_ADJ;
+import static com.android.server.am.ProcessList.HOME_APP_ADJ;
+import static com.android.server.am.ProcessList.PERCEPTIBLE_APP_ADJ;
+import static com.android.server.am.ProcessList.PERCEPTIBLE_LOW_APP_ADJ;
+import static com.android.server.am.ProcessList.PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ;
+import static com.android.server.am.ProcessList.PERSISTENT_PROC_ADJ;
+import static com.android.server.am.ProcessList.PERSISTENT_SERVICE_ADJ;
+import static com.android.server.am.ProcessList.PREVIOUS_APP_ADJ;
+import static com.android.server.am.ProcessList.SCHED_GROUP_BACKGROUND;
+import static com.android.server.am.ProcessList.SCHED_GROUP_DEFAULT;
+import static com.android.server.am.ProcessList.SCHED_GROUP_RESTRICTED;
+import static com.android.server.am.ProcessList.SCHED_GROUP_TOP_APP;
+import static com.android.server.am.ProcessList.SCHED_GROUP_TOP_APP_BOUND;
+import static com.android.server.am.ProcessList.SERVICE_ADJ;
+import static com.android.server.am.ProcessList.SERVICE_B_ADJ;
+import static com.android.server.am.ProcessList.UNKNOWN_ADJ;
+import static com.android.server.am.ProcessList.VISIBLE_APP_ADJ;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.AdditionalAnswers.answer;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.anyInt;
+import static org.mockito.Mockito.anyLong;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doCallRealMethod;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+
+import android.app.IApplicationThread;
+import android.app.IServiceConnection;
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.ServiceInfo;
+import android.os.Build;
+import android.os.IBinder;
+import android.os.PowerManagerInternal;
+import android.os.SystemClock;
+import android.util.ArrayMap;
+import android.util.ArraySet;
+import android.util.SparseArray;
+
+import com.android.server.wm.ActivityServiceConnectionsHolder;
+import com.android.server.wm.ActivityTaskManagerService;
+import com.android.server.wm.WindowProcessController;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+
+/**
+ * Test class for {@link OomAdjuster}.
+ *
+ * Build/Install/Run:
+ * atest MockingOomAdjusterTests
+ */
+public class MockingOomAdjusterTests {
+ private static final int MOCKAPP_PID = 12345;
+ private static final int MOCKAPP_UID = 12345;
+ private static final String MOCKAPP_PROCESSNAME = "test #1";
+ private static final String MOCKAPP_PACKAGENAME = "com.android.test.test1";
+ private static final int MOCKAPP2_PID = MOCKAPP_PID + 1;
+ private static final int MOCKAPP2_UID = MOCKAPP_UID + 1;
+ private static final String MOCKAPP2_PROCESSNAME = "test #2";
+ private static final String MOCKAPP2_PACKAGENAME = "com.android.test.test2";
+ private static final int MOCKAPP3_PID = MOCKAPP_PID + 2;
+ private static final int MOCKAPP3_UID = MOCKAPP_UID + 2;
+ private static final String MOCKAPP3_PROCESSNAME = "test #3";
+ private static final String MOCKAPP3_PACKAGENAME = "com.android.test.test3";
+ private static final int MOCKAPP4_PID = MOCKAPP_PID + 3;
+ private static final int MOCKAPP4_UID = MOCKAPP_UID + 3;
+ private static final String MOCKAPP4_PROCESSNAME = "test #4";
+ private static final String MOCKAPP4_PACKAGENAME = "com.android.test.test4";
+ private static final int MOCKAPP5_PID = MOCKAPP_PID + 4;
+ private static final int MOCKAPP5_UID = MOCKAPP_UID + 4;
+ private static final String MOCKAPP5_PROCESSNAME = "test #5";
+ private static final String MOCKAPP5_PACKAGENAME = "com.android.test.test5";
+ private static Context sContext;
+ private static ActivityManagerService sService;
+
+ @BeforeClass
+ public static void setUpOnce() {
+ sContext = getInstrumentation().getTargetContext();
+ System.setProperty("dexmaker.share_classloader", "true");
+
+ sService = mock(ActivityManagerService.class);
+ sService.mActivityTaskManager = new ActivityTaskManagerService(sContext);
+ sService.mActivityTaskManager.initialize(null, null, sContext.getMainLooper());
+ sService.mAtmInternal = spy(sService.mActivityTaskManager.getAtmInternal());
+
+ sService.mConstants = new ActivityManagerConstants(sContext, sService,
+ sContext.getMainThreadHandler());
+ setFieldValue(ActivityManagerService.class, sService, "mProcessList",
+ new ProcessList());
+ setFieldValue(ActivityManagerService.class, sService, "mHandler",
+ mock(ActivityManagerService.MainHandler.class));
+ setFieldValue(ActivityManagerService.class, sService, "mProcessStats",
+ mock(ProcessStatsService.class));
+ setFieldValue(ActivityManagerService.class, sService, "mBackupTargets",
+ mock(SparseArray.class));
+ setFieldValue(ActivityManagerService.class, sService, "mOomAdjProfiler",
+ mock(OomAdjProfiler.class));
+ doReturn(new ActivityManagerService.ProcessChangeItem()).when(sService)
+ .enqueueProcessChangeItemLocked(anyInt(), anyInt());
+ sService.mOomAdjuster = new OomAdjuster(sService, sService.mProcessList,
+ mock(ActiveUids.class));
+ sService.mOomAdjuster.mAdjSeq = 10000;
+ }
+
+ private static <T> void setFieldValue(Class clazz, Object obj, String fieldName, T val) {
+ try {
+ Field field = clazz.getDeclaredField(fieldName);
+ field.setAccessible(true);
+ Field mfield = Field.class.getDeclaredField("accessFlags");
+ mfield.setAccessible(true);
+ mfield.setInt(field, mfield.getInt(field) & ~(Modifier.FINAL | Modifier.PRIVATE));
+ field.set(obj, val);
+ } catch (NoSuchFieldException | IllegalAccessException e) {
+ }
+ }
+
+ @SuppressWarnings("GuardedBy")
+ @Test
+ public void testUpdateOomAdj_DoOne_Persistent_TopUi_Sleeping() {
+ ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+ MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, true));
+ app.maxAdj = PERSISTENT_PROC_ADJ;
+ app.setHasTopUi(true);
+ sService.mWakefulness = PowerManagerInternal.WAKEFULNESS_ASLEEP;
+ sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
+ sService.mWakefulness = PowerManagerInternal.WAKEFULNESS_AWAKE;
+
+ assertProcStates(app, PROCESS_STATE_BOUND_FOREGROUND_SERVICE, PERSISTENT_PROC_ADJ,
+ SCHED_GROUP_RESTRICTED);
+ }
+
+ @SuppressWarnings("GuardedBy")
+ @Test
+ public void testUpdateOomAdj_DoOne_Persistent_TopUi_Awake() {
+ ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+ MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, true));
+ app.maxAdj = PERSISTENT_PROC_ADJ;
+ app.setHasTopUi(true);
+ sService.mWakefulness = PowerManagerInternal.WAKEFULNESS_AWAKE;
+ sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
+
+ assertProcStates(app, PROCESS_STATE_PERSISTENT_UI, PERSISTENT_PROC_ADJ,
+ SCHED_GROUP_TOP_APP);
+ }
+
+ @SuppressWarnings("GuardedBy")
+ @Test
+ public void testUpdateOomAdj_DoOne_Persistent_TopApp() {
+ ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+ MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, true));
+ app.maxAdj = PERSISTENT_PROC_ADJ;
+ doReturn(app).when(sService).getTopAppLocked();
+ sService.mWakefulness = PowerManagerInternal.WAKEFULNESS_AWAKE;
+ sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
+ doReturn(null).when(sService).getTopAppLocked();
+
+ assertProcStates(app, PROCESS_STATE_PERSISTENT_UI, PERSISTENT_PROC_ADJ,
+ SCHED_GROUP_TOP_APP);
+ }
+
+ @SuppressWarnings("GuardedBy")
+ @Test
+ public void testUpdateOomAdj_DoOne_TopApp_Awake() {
+ ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+ MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, true));
+ doReturn(PROCESS_STATE_TOP).when(sService.mAtmInternal).getTopProcessState();
+ doReturn(app).when(sService).getTopAppLocked();
+ sService.mWakefulness = PowerManagerInternal.WAKEFULNESS_AWAKE;
+ sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
+ doReturn(null).when(sService).getTopAppLocked();
+
+ assertProcStates(app, PROCESS_STATE_TOP, FOREGROUND_APP_ADJ, SCHED_GROUP_TOP_APP);
+ }
+
+ @SuppressWarnings("GuardedBy")
+ @Test
+ public void testUpdateOomAdj_DoOne_RunningAnimations() {
+ ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+ MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, true));
+ doReturn(PROCESS_STATE_TOP_SLEEPING).when(sService.mAtmInternal).getTopProcessState();
+ app.runningRemoteAnimation = true;
+ sService.mWakefulness = PowerManagerInternal.WAKEFULNESS_AWAKE;
+ sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
+ doReturn(PROCESS_STATE_TOP).when(sService.mAtmInternal).getTopProcessState();
+
+ assertProcStates(app, PROCESS_STATE_TOP_SLEEPING, VISIBLE_APP_ADJ, SCHED_GROUP_TOP_APP);
+ }
+
+ @SuppressWarnings("GuardedBy")
+ @Test
+ public void testUpdateOomAdj_DoOne_RunningInstrumentation() {
+ ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+ MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, true));
+ doReturn(mock(ActiveInstrumentation.class)).when(app).getActiveInstrumentation();
+ sService.mWakefulness = PowerManagerInternal.WAKEFULNESS_AWAKE;
+ sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
+ doCallRealMethod().when(app).getActiveInstrumentation();
+
+ assertProcStates(app, PROCESS_STATE_FOREGROUND_SERVICE, FOREGROUND_APP_ADJ,
+ SCHED_GROUP_DEFAULT);
+ }
+
+ @SuppressWarnings("GuardedBy")
+ @Test
+ public void testUpdateOomAdj_DoOne_ReceivingBroadcast() {
+ ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+ MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, true));
+ doReturn(true).when(sService).isReceivingBroadcastLocked(any(ProcessRecord.class),
+ any(ArraySet.class));
+ sService.mWakefulness = PowerManagerInternal.WAKEFULNESS_AWAKE;
+ sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
+ doReturn(false).when(sService).isReceivingBroadcastLocked(any(ProcessRecord.class),
+ any(ArraySet.class));
+
+ assertProcStates(app, PROCESS_STATE_RECEIVER, FOREGROUND_APP_ADJ, SCHED_GROUP_BACKGROUND);
+ }
+
+ @SuppressWarnings("GuardedBy")
+ @Test
+ public void testUpdateOomAdj_DoOne_ExecutingService() {
+ ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+ MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, true));
+ app.executingServices.add(mock(ServiceRecord.class));
+ sService.mWakefulness = PowerManagerInternal.WAKEFULNESS_AWAKE;
+ sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
+
+ assertProcStates(app, PROCESS_STATE_SERVICE, FOREGROUND_APP_ADJ, SCHED_GROUP_BACKGROUND);
+ }
+
+ @SuppressWarnings("GuardedBy")
+ @Test
+ public void testUpdateOomAdj_DoOne_TopApp_Sleeping() {
+ ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+ MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, true));
+ doReturn(PROCESS_STATE_TOP_SLEEPING).when(sService.mAtmInternal).getTopProcessState();
+ doReturn(app).when(sService).getTopAppLocked();
+ sService.mWakefulness = PowerManagerInternal.WAKEFULNESS_ASLEEP;
+ sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
+ doReturn(null).when(sService).getTopAppLocked();
+ doReturn(PROCESS_STATE_TOP).when(sService.mAtmInternal).getTopProcessState();
+ sService.mWakefulness = PowerManagerInternal.WAKEFULNESS_AWAKE;
+
+ assertProcStates(app, PROCESS_STATE_TOP_SLEEPING, FOREGROUND_APP_ADJ,
+ SCHED_GROUP_BACKGROUND);
+ }
+
+ @SuppressWarnings("GuardedBy")
+ @Test
+ public void testUpdateOomAdj_DoOne_CachedEmpty() {
+ ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+ MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, true));
+ app.setCurRawAdj(CACHED_APP_MIN_ADJ);
+ doReturn(null).when(sService).getTopAppLocked();
+ sService.mWakefulness = PowerManagerInternal.WAKEFULNESS_AWAKE;
+ sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
+
+ assertProcStates(app, PROCESS_STATE_CACHED_EMPTY, CACHED_APP_MIN_ADJ,
+ SCHED_GROUP_BACKGROUND);
+ }
+
+ @SuppressWarnings("GuardedBy")
+ @Test
+ public void testUpdateOomAdj_DoOne_VisibleActivities() {
+ ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+ MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, true));
+ doReturn(mock(WindowProcessController.class)).when(app).getWindowProcessController();
+ WindowProcessController wpc = app.getWindowProcessController();
+ doReturn(true).when(wpc).hasActivities();
+ doAnswer(answer((minTaskLayer, callback) -> {
+ Field field = callback.getClass().getDeclaredField("adj");
+ field.set(callback, VISIBLE_APP_ADJ);
+ field = callback.getClass().getDeclaredField("foregroundActivities");
+ field.set(callback, true);
+ field = callback.getClass().getDeclaredField("procState");
+ field.set(callback, PROCESS_STATE_TOP);
+ field = callback.getClass().getDeclaredField("schedGroup");
+ field.set(callback, SCHED_GROUP_TOP_APP);
+ return 0;
+ })).when(wpc).computeOomAdjFromActivities(anyInt(),
+ any(WindowProcessController.ComputeOomAdjCallback.class));
+ sService.mWakefulness = PowerManagerInternal.WAKEFULNESS_AWAKE;
+ sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
+ doCallRealMethod().when(app).getWindowProcessController();
+
+ assertProcStates(app, PROCESS_STATE_TOP, VISIBLE_APP_ADJ, SCHED_GROUP_TOP_APP);
+ }
+
+ @SuppressWarnings("GuardedBy")
+ @Test
+ public void testUpdateOomAdj_DoOne_RecentTasks() {
+ ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+ MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, true));
+ doReturn(true).when(app).hasRecentTasks();
+ app.lastTopTime = SystemClock.uptimeMillis();
+ sService.mWakefulness = PowerManagerInternal.WAKEFULNESS_AWAKE;
+ sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
+ doCallRealMethod().when(app).hasRecentTasks();
+
+ assertEquals(PROCESS_STATE_CACHED_RECENT, app.setProcState);
+ }
+
+ @SuppressWarnings("GuardedBy")
+ @Test
+ public void testUpdateOomAdj_DoOne_FgServiceLocation() {
+ ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+ MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, true));
+ app.setHasForegroundServices(true, ServiceInfo.FOREGROUND_SERVICE_TYPE_LOCATION);
+ 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,
+ SCHED_GROUP_DEFAULT);
+ }
+
+ @SuppressWarnings("GuardedBy")
+ @Test
+ public void testUpdateOomAdj_DoOne_FgService() {
+ ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+ MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, true));
+ app.setHasForegroundServices(true, 0);
+ sService.mWakefulness = PowerManagerInternal.WAKEFULNESS_AWAKE;
+ sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
+
+ assertProcStates(app, PROCESS_STATE_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ,
+ SCHED_GROUP_DEFAULT);
+ }
+
+ @SuppressWarnings("GuardedBy")
+ @Test
+ public void testUpdateOomAdj_DoOne_OverlayUi() {
+ ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+ MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, true));
+ app.setHasOverlayUi(true);
+ sService.mWakefulness = PowerManagerInternal.WAKEFULNESS_AWAKE;
+ sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
+
+ assertProcStates(app, PROCESS_STATE_IMPORTANT_FOREGROUND, PERCEPTIBLE_APP_ADJ,
+ SCHED_GROUP_DEFAULT);
+ }
+
+ @SuppressWarnings("GuardedBy")
+ @Test
+ public void testUpdateOomAdj_DoOne_PerceptibleRecent() {
+ ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+ MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, true));
+ app.setHasForegroundServices(true, 0);
+ app.lastTopTime = SystemClock.uptimeMillis();
+ sService.mWakefulness = PowerManagerInternal.WAKEFULNESS_AWAKE;
+ sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
+
+ assertProcStates(app, PROCESS_STATE_FOREGROUND_SERVICE,
+ PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ, SCHED_GROUP_DEFAULT);
+ }
+
+ @SuppressWarnings("GuardedBy")
+ @Test
+ public void testUpdateOomAdj_DoOne_Toast() {
+ ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+ MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, true));
+ app.forcingToImportant = new Object();
+ sService.mWakefulness = PowerManagerInternal.WAKEFULNESS_AWAKE;
+ sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
+
+ assertProcStates(app, PROCESS_STATE_TRANSIENT_BACKGROUND, PERCEPTIBLE_APP_ADJ,
+ SCHED_GROUP_DEFAULT);
+ }
+
+ @SuppressWarnings("GuardedBy")
+ @Test
+ public void testUpdateOomAdj_DoOne_HeavyWeight() {
+ ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+ MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, true));
+ doReturn(true).when(sService.mAtmInternal).isHeavyWeightProcess(any(
+ WindowProcessController.class));
+ sService.mWakefulness = PowerManagerInternal.WAKEFULNESS_AWAKE;
+ sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
+ doReturn(false).when(sService.mAtmInternal).isHeavyWeightProcess(any(
+ WindowProcessController.class));
+
+ assertProcStates(app, PROCESS_STATE_HEAVY_WEIGHT, HEAVY_WEIGHT_APP_ADJ,
+ SCHED_GROUP_BACKGROUND);
+ }
+
+ @SuppressWarnings("GuardedBy")
+ @Test
+ public void testUpdateOomAdj_DoOne_HomeApp() {
+ ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+ MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, true));
+ doReturn(mock(WindowProcessController.class)).when(app).getWindowProcessController();
+ WindowProcessController wpc = app.getWindowProcessController();
+ doReturn(true).when(wpc).isHomeProcess();
+ sService.mWakefulness = PowerManagerInternal.WAKEFULNESS_AWAKE;
+ sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
+
+ assertProcStates(app, PROCESS_STATE_HOME, HOME_APP_ADJ, SCHED_GROUP_BACKGROUND);
+ }
+
+ @SuppressWarnings("GuardedBy")
+ @Test
+ public void testUpdateOomAdj_DoOne_PreviousApp() {
+ ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+ MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, true));
+ doReturn(mock(WindowProcessController.class)).when(app).getWindowProcessController();
+ WindowProcessController wpc = app.getWindowProcessController();
+ doReturn(true).when(wpc).isPreviousProcess();
+ doReturn(true).when(app).hasActivities();
+ sService.mWakefulness = PowerManagerInternal.WAKEFULNESS_AWAKE;
+ sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
+
+ assertProcStates(app, PROCESS_STATE_LAST_ACTIVITY, PREVIOUS_APP_ADJ,
+ SCHED_GROUP_BACKGROUND);
+ }
+
+ @SuppressWarnings("GuardedBy")
+ @Test
+ public void testUpdateOomAdj_DoOne_Backup() {
+ ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+ MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, true));
+ BackupRecord backupTarget = new BackupRecord(null, 0, 0);
+ backupTarget.app = app;
+ doReturn(backupTarget).when(sService.mBackupTargets).get(anyInt());
+ sService.mWakefulness = PowerManagerInternal.WAKEFULNESS_AWAKE;
+ sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
+ doReturn(null).when(sService.mBackupTargets).get(anyInt());
+
+ assertProcStates(app, PROCESS_STATE_TRANSIENT_BACKGROUND, BACKUP_APP_ADJ,
+ SCHED_GROUP_BACKGROUND);
+ }
+
+ @SuppressWarnings("GuardedBy")
+ @Test
+ public void testUpdateOomAdj_DoOne_ClientActivities() {
+ ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+ MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, true));
+ doReturn(true).when(app).hasClientActivities();
+ sService.mWakefulness = PowerManagerInternal.WAKEFULNESS_AWAKE;
+ sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
+
+ assertEquals(PROCESS_STATE_CACHED_ACTIVITY_CLIENT, app.setProcState);
+ }
+
+ @SuppressWarnings("GuardedBy")
+ @Test
+ public void testUpdateOomAdj_DoOne_TreatLikeActivity() {
+ ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+ MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, true));
+ app.treatLikeActivity = true;
+ sService.mWakefulness = PowerManagerInternal.WAKEFULNESS_AWAKE;
+ sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
+
+ assertEquals(PROCESS_STATE_CACHED_ACTIVITY, app.setProcState);
+ }
+
+ @SuppressWarnings("GuardedBy")
+ @Test
+ public void testUpdateOomAdj_DoOne_ServiceB() {
+ ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+ MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
+ app.serviceb = true;
+ ServiceRecord s = mock(ServiceRecord.class);
+ doReturn(new ArrayMap<IBinder, ArrayList<ConnectionRecord>>()).when(s).getConnections();
+ s.startRequested = true;
+ s.lastActivity = SystemClock.uptimeMillis();
+ app.services.add(s);
+ sService.mWakefulness = PowerManagerInternal.WAKEFULNESS_AWAKE;
+ sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
+
+ assertProcStates(app, PROCESS_STATE_SERVICE, SERVICE_B_ADJ, SCHED_GROUP_BACKGROUND);
+ }
+
+ @SuppressWarnings("GuardedBy")
+ @Test
+ public void testUpdateOomAdj_DoOne_MaxAdj() {
+ ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+ MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
+ app.maxAdj = PERCEPTIBLE_LOW_APP_ADJ;
+ sService.mWakefulness = PowerManagerInternal.WAKEFULNESS_AWAKE;
+ sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
+
+ assertProcStates(app, PROCESS_STATE_CACHED_EMPTY, PERCEPTIBLE_LOW_APP_ADJ,
+ SCHED_GROUP_DEFAULT);
+ }
+
+ @SuppressWarnings("GuardedBy")
+ @Test
+ public void testUpdateOomAdj_DoOne_Service_Started() {
+ ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+ MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
+ ServiceRecord s = mock(ServiceRecord.class);
+ doReturn(new ArrayMap<IBinder, ArrayList<ConnectionRecord>>()).when(s).getConnections();
+ s.startRequested = true;
+ s.lastActivity = SystemClock.uptimeMillis();
+ app.services.add(s);
+ sService.mWakefulness = PowerManagerInternal.WAKEFULNESS_AWAKE;
+ sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
+
+ assertProcStates(app, PROCESS_STATE_SERVICE, SERVICE_ADJ, SCHED_GROUP_BACKGROUND);
+ }
+
+ @SuppressWarnings("GuardedBy")
+ @Test
+ public void testUpdateOomAdj_DoOne_Service_Started_WaivePriority() {
+ ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+ MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, true));
+ ProcessRecord client = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
+ MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
+ ServiceRecord s = bindService(app, client, null, Context.BIND_WAIVE_PRIORITY,
+ mock(IBinder.class));
+ s.startRequested = true;
+ sService.mWakefulness = PowerManagerInternal.WAKEFULNESS_AWAKE;
+ doReturn(PROCESS_STATE_TOP).when(sService.mAtmInternal).getTopProcessState();
+ doReturn(client).when(sService).getTopAppLocked();
+ sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
+ doReturn(null).when(sService).getTopAppLocked();
+
+ assertProcStates(app, PROCESS_STATE_SERVICE, UNKNOWN_ADJ, SCHED_GROUP_BACKGROUND);
+ }
+
+ @SuppressWarnings("GuardedBy")
+ @Test
+ public void testUpdateOomAdj_DoOne_Service_Started_WaivePriority_TreatLikeActivity() {
+ ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+ MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
+ ProcessRecord client = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
+ MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
+ bindService(app, client, null, Context.BIND_WAIVE_PRIORITY
+ | Context.BIND_TREAT_LIKE_ACTIVITY, mock(IBinder.class));
+ sService.mWakefulness = PowerManagerInternal.WAKEFULNESS_AWAKE;
+ sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
+
+ assertEquals(PROCESS_STATE_CACHED_ACTIVITY, app.setProcState);
+ }
+
+ @SuppressWarnings("GuardedBy")
+ @Test
+ public void testUpdateOomAdj_DoOne_Service_Started_WaivePriority_AdjustWithActivity() {
+ ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+ MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
+ ProcessRecord client = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
+ MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
+ IBinder binder = mock(IBinder.class);
+ ServiceRecord s = bindService(app, client, null, Context.BIND_WAIVE_PRIORITY
+ | Context.BIND_ADJUST_WITH_ACTIVITY | Context.BIND_IMPORTANT, binder);
+ ConnectionRecord cr = s.getConnections().get(binder).get(0);
+ setFieldValue(ConnectionRecord.class, cr, "activity",
+ mock(ActivityServiceConnectionsHolder.class));
+ doReturn(true).when(cr.activity).isActivityVisible();
+ sService.mWakefulness = PowerManagerInternal.WAKEFULNESS_AWAKE;
+ sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
+
+ assertEquals(FOREGROUND_APP_ADJ, app.setAdj);
+ assertEquals(SCHED_GROUP_TOP_APP_BOUND, app.setSchedGroup);
+ }
+
+ @SuppressWarnings("GuardedBy")
+ @Test
+ public void testUpdateOomAdj_DoOne_Service_Self() {
+ ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+ MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
+ bindService(app, app, null, 0, mock(IBinder.class));
+ sService.mWakefulness = PowerManagerInternal.WAKEFULNESS_AWAKE;
+ sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
+
+ assertProcStates(app, PROCESS_STATE_CACHED_EMPTY, UNKNOWN_ADJ, SCHED_GROUP_BACKGROUND);
+ }
+
+ @SuppressWarnings("GuardedBy")
+ @Test
+ public void testUpdateOomAdj_DoOne_Service_CachedActivity() {
+ ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+ MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
+ ProcessRecord client = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
+ MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
+ client.treatLikeActivity = true;
+ bindService(app, client, null, 0, mock(IBinder.class));
+ sService.mWakefulness = PowerManagerInternal.WAKEFULNESS_AWAKE;
+ sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
+
+ assertEquals(PROCESS_STATE_CACHED_EMPTY, app.setProcState);
+ }
+
+ @SuppressWarnings("GuardedBy")
+ @Test
+ public void testUpdateOomAdj_DoOne_Service_AllowOomManagement() {
+ ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+ MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, true));
+ doReturn(mock(WindowProcessController.class)).when(app).getWindowProcessController();
+ WindowProcessController wpc = app.getWindowProcessController();
+ doReturn(false).when(wpc).isHomeProcess();
+ doReturn(true).when(wpc).isPreviousProcess();
+ doReturn(true).when(app).hasActivities();
+ ProcessRecord client = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
+ MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
+ bindService(app, client, null, Context.BIND_ALLOW_OOM_MANAGEMENT, mock(IBinder.class));
+ doReturn(PROCESS_STATE_TOP).when(sService.mAtmInternal).getTopProcessState();
+ doReturn(client).when(sService).getTopAppLocked();
+ sService.mWakefulness = PowerManagerInternal.WAKEFULNESS_AWAKE;
+ sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
+ doReturn(null).when(sService).getTopAppLocked();
+
+ assertEquals(PREVIOUS_APP_ADJ, app.setAdj);
+ }
+
+ @SuppressWarnings("GuardedBy")
+ @Test
+ public void testUpdateOomAdj_DoOne_Service_BoundByPersistentService() {
+ ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+ MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
+ ProcessRecord client = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
+ MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
+ bindService(app, client, null, Context.BIND_FOREGROUND_SERVICE, mock(IBinder.class));
+ client.maxAdj = PERSISTENT_PROC_ADJ;
+ client.setHasTopUi(true);
+ sService.mWakefulness = PowerManagerInternal.WAKEFULNESS_AWAKE;
+ sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
+
+ assertProcStates(app, PROCESS_STATE_BOUND_FOREGROUND_SERVICE, VISIBLE_APP_ADJ,
+ SCHED_GROUP_DEFAULT);
+ }
+
+ @SuppressWarnings("GuardedBy")
+ @Test
+ public void testUpdateOomAdj_DoOne_Service_Bound_ImportantFg() {
+ ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+ MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
+ ProcessRecord client = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
+ MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
+ bindService(app, client, null, Context.BIND_IMPORTANT, mock(IBinder.class));
+ client.executingServices.add(mock(ServiceRecord.class));
+ sService.mWakefulness = PowerManagerInternal.WAKEFULNESS_AWAKE;
+ sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
+
+ assertEquals(FOREGROUND_APP_ADJ, app.setAdj);
+ }
+
+ @SuppressWarnings("GuardedBy")
+ @Test
+ public void testUpdateOomAdj_DoOne_Service_BoundByTop() {
+ ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+ MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
+ ProcessRecord client = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
+ MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
+ bindService(app, client, null, 0, mock(IBinder.class));
+ doReturn(PROCESS_STATE_TOP).when(sService.mAtmInternal).getTopProcessState();
+ doReturn(client).when(sService).getTopAppLocked();
+ sService.mWakefulness = PowerManagerInternal.WAKEFULNESS_AWAKE;
+ sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
+ doReturn(null).when(sService).getTopAppLocked();
+
+ assertProcStates(app, PROCESS_STATE_BOUND_TOP, VISIBLE_APP_ADJ, SCHED_GROUP_DEFAULT);
+ }
+
+ @SuppressWarnings("GuardedBy")
+ @Test
+ public void testUpdateOomAdj_DoOne_Service_BoundFgService() {
+ ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+ MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
+ ProcessRecord client = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
+ MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
+ bindService(app, client, null, Context.BIND_FOREGROUND_SERVICE, mock(IBinder.class));
+ client.maxAdj = PERSISTENT_PROC_ADJ;
+ sService.mWakefulness = PowerManagerInternal.WAKEFULNESS_AWAKE;
+ sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
+
+ assertEquals(PROCESS_STATE_BOUND_FOREGROUND_SERVICE, app.setProcState);
+ }
+
+ @SuppressWarnings("GuardedBy")
+ @Test
+ public void testUpdateOomAdj_DoOne_Service_BoundNotForeground() {
+ ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+ MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
+ ProcessRecord client = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
+ MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
+ bindService(app, client, null, Context.BIND_NOT_FOREGROUND, mock(IBinder.class));
+ client.maxAdj = PERSISTENT_PROC_ADJ;
+ sService.mWakefulness = PowerManagerInternal.WAKEFULNESS_AWAKE;
+ sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
+
+ assertEquals(PROCESS_STATE_TRANSIENT_BACKGROUND, app.setProcState);
+ }
+
+ @SuppressWarnings("GuardedBy")
+ @Test
+ public void testUpdateOomAdj_DoOne_Service_ImportantFgService() {
+ ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+ MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
+ ProcessRecord client = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
+ MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
+ bindService(app, client, null, 0, mock(IBinder.class));
+ client.setHasForegroundServices(true, 0);
+ sService.mWakefulness = PowerManagerInternal.WAKEFULNESS_AWAKE;
+ sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
+
+ assertEquals(PROCESS_STATE_FOREGROUND_SERVICE, app.setProcState);
+ }
+
+ @SuppressWarnings("GuardedBy")
+ @Test
+ public void testUpdateOomAdj_DoOne_Service_BoundByBackup_AboveClient() {
+ ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+ MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
+ ProcessRecord client = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
+ MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
+ bindService(app, client, null, Context.BIND_ABOVE_CLIENT, mock(IBinder.class));
+ BackupRecord backupTarget = new BackupRecord(null, 0, 0);
+ backupTarget.app = client;
+ doReturn(backupTarget).when(sService.mBackupTargets).get(anyInt());
+ sService.mWakefulness = PowerManagerInternal.WAKEFULNESS_AWAKE;
+ sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
+ doReturn(null).when(sService.mBackupTargets).get(anyInt());
+
+ assertEquals(BACKUP_APP_ADJ, app.setAdj);
+
+ client.maxAdj = PERSISTENT_PROC_ADJ;
+ sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
+
+ assertEquals(PERSISTENT_SERVICE_ADJ, app.setAdj);
+ }
+
+ @SuppressWarnings("GuardedBy")
+ @Test
+ public void testUpdateOomAdj_DoOne_Service_NotPerceptible() {
+ ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+ MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
+ ProcessRecord client = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
+ MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
+ bindService(app, client, null, Context.BIND_NOT_PERCEPTIBLE, mock(IBinder.class));
+ client.runningRemoteAnimation = true;
+ sService.mWakefulness = PowerManagerInternal.WAKEFULNESS_AWAKE;
+ sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
+
+ assertEquals(PERCEPTIBLE_LOW_APP_ADJ, app.setAdj);
+ }
+
+ @SuppressWarnings("GuardedBy")
+ @Test
+ public void testUpdateOomAdj_DoOne_Service_NotVisible() {
+ ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+ MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
+ ProcessRecord client = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
+ MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
+ bindService(app, client, null, Context.BIND_NOT_VISIBLE, mock(IBinder.class));
+ client.runningRemoteAnimation = true;
+ sService.mWakefulness = PowerManagerInternal.WAKEFULNESS_AWAKE;
+ sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
+
+ assertEquals(PERCEPTIBLE_APP_ADJ, app.setAdj);
+ }
+
+ @SuppressWarnings("GuardedBy")
+ @Test
+ public void testUpdateOomAdj_DoOne_Service_Perceptible() {
+ ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+ MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
+ ProcessRecord client = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
+ MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
+ bindService(app, client, null, 0, mock(IBinder.class));
+ client.setHasOverlayUi(true);
+ sService.mWakefulness = PowerManagerInternal.WAKEFULNESS_AWAKE;
+ sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
+
+ assertEquals(PERCEPTIBLE_APP_ADJ, app.setAdj);
+ }
+
+ @SuppressWarnings("GuardedBy")
+ @Test
+ public void testUpdateOomAdj_DoOne_Service_Other() {
+ ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+ MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
+ ProcessRecord client = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
+ MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
+ bindService(app, client, null, 0, mock(IBinder.class));
+ client.runningRemoteAnimation = true;
+ sService.mWakefulness = PowerManagerInternal.WAKEFULNESS_AWAKE;
+ sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
+
+ assertEquals(VISIBLE_APP_ADJ, app.setAdj);
+ }
+
+ @SuppressWarnings("GuardedBy")
+ @Test
+ public void testUpdateOomAdj_DoOne_Service_Bind_ImportantBg() {
+ ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+ MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
+ ProcessRecord client = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
+ MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
+ bindService(app, client, null, Context.BIND_IMPORTANT_BACKGROUND, mock(IBinder.class));
+ client.setHasOverlayUi(true);
+ sService.mWakefulness = PowerManagerInternal.WAKEFULNESS_AWAKE;
+ sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
+
+ assertEquals(PROCESS_STATE_IMPORTANT_BACKGROUND, app.setProcState);
+ }
+
+ @SuppressWarnings("GuardedBy")
+ @Test
+ public void testUpdateOomAdj_DoOne_Provider_Self() {
+ ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+ MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
+ bindProvider(app, app, null, null, false);
+ sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
+
+ assertProcStates(app, PROCESS_STATE_CACHED_EMPTY, UNKNOWN_ADJ, SCHED_GROUP_BACKGROUND);
+ }
+
+ @SuppressWarnings("GuardedBy")
+ @Test
+ public void testUpdateOomAdj_DoOne_Provider_Cached_Activity() {
+ ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+ MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
+ ProcessRecord client = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
+ MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
+ bindProvider(app, client, null, null, false);
+ client.treatLikeActivity = true;
+ sService.mWakefulness = PowerManagerInternal.WAKEFULNESS_AWAKE;
+ sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
+
+ assertProcStates(app, PROCESS_STATE_CACHED_EMPTY, UNKNOWN_ADJ, SCHED_GROUP_BACKGROUND);
+ }
+
+ @SuppressWarnings("GuardedBy")
+ @Test
+ public void testUpdateOomAdj_DoOne_Provider_TopApp() {
+ ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+ MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
+ ProcessRecord client = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
+ MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
+ bindProvider(app, client, null, null, false);
+ doReturn(PROCESS_STATE_TOP).when(sService.mAtmInternal).getTopProcessState();
+ doReturn(client).when(sService).getTopAppLocked();
+ sService.mWakefulness = PowerManagerInternal.WAKEFULNESS_AWAKE;
+ sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
+ doReturn(null).when(sService).getTopAppLocked();
+
+ assertProcStates(app, PROCESS_STATE_BOUND_TOP, FOREGROUND_APP_ADJ, SCHED_GROUP_DEFAULT);
+ }
+
+ @SuppressWarnings("GuardedBy")
+ @Test
+ public void testUpdateOomAdj_DoOne_Provider_FgService() {
+ ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+ MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
+ ProcessRecord client = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
+ MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
+ client.setHasForegroundServices(true, 0);
+ bindProvider(app, client, null, null, false);
+ sService.mWakefulness = PowerManagerInternal.WAKEFULNESS_AWAKE;
+ sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
+
+ assertProcStates(app, PROCESS_STATE_BOUND_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ,
+ SCHED_GROUP_DEFAULT);
+ }
+
+ @SuppressWarnings("GuardedBy")
+ @Test
+ public void testUpdateOomAdj_DoOne_Provider_ExternalProcessHandles() {
+ ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+ MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
+ ProcessRecord client = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
+ MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
+ bindProvider(app, client, null, null, true);
+ sService.mWakefulness = PowerManagerInternal.WAKEFULNESS_AWAKE;
+ sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
+
+ assertProcStates(app, PROCESS_STATE_IMPORTANT_FOREGROUND, FOREGROUND_APP_ADJ,
+ SCHED_GROUP_DEFAULT);
+ }
+
+ @SuppressWarnings("GuardedBy")
+ @Test
+ public void testUpdateOomAdj_DoOne_Provider_Retention() {
+ ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+ MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
+ app.lastProviderTime = SystemClock.uptimeMillis();
+ sService.mWakefulness = PowerManagerInternal.WAKEFULNESS_AWAKE;
+ sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
+
+ assertProcStates(app, PROCESS_STATE_LAST_ACTIVITY, PREVIOUS_APP_ADJ,
+ SCHED_GROUP_BACKGROUND);
+ }
+
+ @SuppressWarnings("GuardedBy")
+ @Test
+ public void testUpdateOomAdj_DoOne_Service_Chain_BoundByTop() {
+ ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+ MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
+ ProcessRecord client = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
+ MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
+ bindService(app, client, null, 0, mock(IBinder.class));
+ ProcessRecord client2 = spy(makeDefaultProcessRecord(MOCKAPP3_PID, MOCKAPP3_UID,
+ MOCKAPP3_PROCESSNAME, MOCKAPP3_PACKAGENAME, false));
+ bindService(client, client2, null, 0, mock(IBinder.class));
+ doReturn(PROCESS_STATE_TOP).when(sService.mAtmInternal).getTopProcessState();
+ doReturn(client2).when(sService).getTopAppLocked();
+ sService.mWakefulness = PowerManagerInternal.WAKEFULNESS_AWAKE;
+ sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
+ doReturn(null).when(sService).getTopAppLocked();
+
+ assertProcStates(app, PROCESS_STATE_FOREGROUND_SERVICE, VISIBLE_APP_ADJ,
+ SCHED_GROUP_DEFAULT);
+ }
+
+ @SuppressWarnings("GuardedBy")
+ @Test
+ public void testUpdateOomAdj_DoOne_Service_BoundByFgService_Branch() {
+ ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+ MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
+ ProcessRecord client = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
+ MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
+ bindService(app, client, null, 0, mock(IBinder.class));
+ ProcessRecord client2 = spy(makeDefaultProcessRecord(MOCKAPP3_PID, MOCKAPP3_UID,
+ MOCKAPP3_PROCESSNAME, MOCKAPP3_PACKAGENAME, false));
+ bindService(app, client2, null, 0, mock(IBinder.class));
+ client2.setHasForegroundServices(true, 0);
+ sService.mWakefulness = PowerManagerInternal.WAKEFULNESS_AWAKE;
+ sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
+
+ assertProcStates(app, PROCESS_STATE_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ,
+ SCHED_GROUP_DEFAULT);
+ }
+
+ @SuppressWarnings("GuardedBy")
+ @Test
+ public void testUpdateOomAdj_DoOne_Service_Chain_BoundByFgService() {
+ ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+ MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
+ ProcessRecord client = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
+ MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
+ bindService(app, client, null, 0, mock(IBinder.class));
+ ProcessRecord client2 = spy(makeDefaultProcessRecord(MOCKAPP3_PID, MOCKAPP3_UID,
+ MOCKAPP3_PROCESSNAME, MOCKAPP3_PACKAGENAME, false));
+ bindService(client, client2, null, 0, mock(IBinder.class));
+ client2.setHasForegroundServices(true, 0);
+ sService.mWakefulness = PowerManagerInternal.WAKEFULNESS_AWAKE;
+ sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
+
+ assertProcStates(app, PROCESS_STATE_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ,
+ SCHED_GROUP_DEFAULT);
+ }
+
+ @SuppressWarnings("GuardedBy")
+ @Test
+ public void testUpdateOomAdj_DoOne_Service_Chain_BoundByFgService_Cycle() {
+ ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+ MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
+ ProcessRecord client = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
+ MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
+ bindService(app, client, null, 0, mock(IBinder.class));
+ ProcessRecord client2 = spy(makeDefaultProcessRecord(MOCKAPP3_PID, MOCKAPP3_UID,
+ MOCKAPP3_PROCESSNAME, MOCKAPP3_PACKAGENAME, false));
+ bindService(client, client2, null, 0, mock(IBinder.class));
+ client2.setHasForegroundServices(true, 0);
+ bindService(client2, app, null, 0, mock(IBinder.class));
+ sService.mWakefulness = PowerManagerInternal.WAKEFULNESS_AWAKE;
+ sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
+
+ assertProcStates(app, PROCESS_STATE_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ,
+ SCHED_GROUP_DEFAULT);
+ }
+
+ @SuppressWarnings("GuardedBy")
+ @Test
+ public void testUpdateOomAdj_DoOne_Service_Chain_BoundByFgService_Cycle_Branch() {
+ ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+ MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
+ ProcessRecord client = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
+ MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
+ bindService(app, client, null, 0, mock(IBinder.class));
+ ProcessRecord client2 = spy(makeDefaultProcessRecord(MOCKAPP3_PID, MOCKAPP3_UID,
+ MOCKAPP3_PROCESSNAME, MOCKAPP3_PACKAGENAME, false));
+ bindService(client, client2, null, 0, mock(IBinder.class));
+ client2.setHasForegroundServices(true, 0);
+ bindService(client2, app, null, 0, mock(IBinder.class));
+ ProcessRecord client3 = spy(makeDefaultProcessRecord(MOCKAPP4_PID, MOCKAPP4_UID,
+ MOCKAPP4_PROCESSNAME, MOCKAPP4_PACKAGENAME, false));
+ client3.forcingToImportant = new Object();
+ bindService(app, client3, null, 0, mock(IBinder.class));
+ sService.mWakefulness = PowerManagerInternal.WAKEFULNESS_AWAKE;
+ sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
+
+ assertProcStates(app, PROCESS_STATE_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ,
+ SCHED_GROUP_DEFAULT);
+ }
+
+ @SuppressWarnings("GuardedBy")
+ @Test
+ public void testUpdateOomAdj_DoOne_Service_Chain_Perceptible_Cycle_Branch() {
+ ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+ MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
+ ProcessRecord client = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
+ MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
+ bindService(app, client, null, 0, mock(IBinder.class));
+ ProcessRecord client2 = spy(makeDefaultProcessRecord(MOCKAPP3_PID, MOCKAPP3_UID,
+ MOCKAPP3_PROCESSNAME, MOCKAPP3_PACKAGENAME, false));
+ bindService(client, client2, null, 0, mock(IBinder.class));
+ bindService(client2, app, null, 0, mock(IBinder.class));
+ doReturn(mock(WindowProcessController.class)).when(client2).getWindowProcessController();
+ WindowProcessController wpc = client2.getWindowProcessController();
+ doReturn(true).when(wpc).isHomeProcess();
+ ProcessRecord client3 = spy(makeDefaultProcessRecord(MOCKAPP4_PID, MOCKAPP4_UID,
+ MOCKAPP4_PROCESSNAME, MOCKAPP4_PACKAGENAME, false));
+ client3.forcingToImportant = new Object();
+ bindService(app, client3, null, 0, mock(IBinder.class));
+ sService.mWakefulness = PowerManagerInternal.WAKEFULNESS_AWAKE;
+ sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
+
+ assertProcStates(app, PROCESS_STATE_TRANSIENT_BACKGROUND, PERCEPTIBLE_APP_ADJ,
+ SCHED_GROUP_DEFAULT);
+ }
+
+ @SuppressWarnings("GuardedBy")
+ @Test
+ public void testUpdateOomAdj_DoOne_Service_Chain_Perceptible_Cycle_2() {
+ ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+ MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
+ ProcessRecord client = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
+ MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
+ bindService(app, client, null, 0, mock(IBinder.class));
+ ProcessRecord client2 = spy(makeDefaultProcessRecord(MOCKAPP3_PID, MOCKAPP3_UID,
+ MOCKAPP3_PROCESSNAME, MOCKAPP3_PACKAGENAME, false));
+ bindService(client, client2, null, 0, mock(IBinder.class));
+ bindService(client2, app, null, 0, mock(IBinder.class));
+ doReturn(mock(WindowProcessController.class)).when(client2).getWindowProcessController();
+ WindowProcessController wpc = client2.getWindowProcessController();
+ doReturn(true).when(wpc).isHomeProcess();
+ ProcessRecord client3 = spy(makeDefaultProcessRecord(MOCKAPP4_PID, MOCKAPP4_UID,
+ MOCKAPP4_PROCESSNAME, MOCKAPP4_PACKAGENAME, false));
+ ProcessRecord client4 = spy(makeDefaultProcessRecord(MOCKAPP5_PID, MOCKAPP5_UID,
+ MOCKAPP5_PROCESSNAME, MOCKAPP5_PACKAGENAME, false));
+ client4.forcingToImportant = new Object();
+ bindService(app, client4, null, 0, mock(IBinder.class));
+ sService.mWakefulness = PowerManagerInternal.WAKEFULNESS_AWAKE;
+ sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
+
+ assertProcStates(app, PROCESS_STATE_TRANSIENT_BACKGROUND, PERCEPTIBLE_APP_ADJ,
+ SCHED_GROUP_DEFAULT);
+ }
+
+ @SuppressWarnings("GuardedBy")
+ @Test
+ public void testUpdateOomAdj_DoOne_Service_Chain_BoundByFgService_Cycle_Branch_2() {
+ ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+ MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
+ ProcessRecord client = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
+ MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
+ bindService(app, client, null, 0, mock(IBinder.class));
+ ProcessRecord client2 = spy(makeDefaultProcessRecord(MOCKAPP3_PID, MOCKAPP3_UID,
+ MOCKAPP3_PROCESSNAME, MOCKAPP3_PACKAGENAME, false));
+ bindService(client, client2, null, 0, mock(IBinder.class));
+ bindService(client2, app, null, 0, mock(IBinder.class));
+ doReturn(mock(WindowProcessController.class)).when(client2).getWindowProcessController();
+ WindowProcessController wpc = client2.getWindowProcessController();
+ doReturn(true).when(wpc).isHomeProcess();
+ ProcessRecord client3 = spy(makeDefaultProcessRecord(MOCKAPP4_PID, MOCKAPP4_UID,
+ MOCKAPP4_PROCESSNAME, MOCKAPP4_PACKAGENAME, false));
+ client3.forcingToImportant = new Object();
+ bindService(app, client3, null, 0, mock(IBinder.class));
+ ProcessRecord client4 = spy(makeDefaultProcessRecord(MOCKAPP5_PID, MOCKAPP5_UID,
+ MOCKAPP5_PROCESSNAME, MOCKAPP5_PACKAGENAME, false));
+ client4.setHasForegroundServices(true, 0);
+ bindService(app, client4, null, 0, mock(IBinder.class));
+ sService.mWakefulness = PowerManagerInternal.WAKEFULNESS_AWAKE;
+ sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
+
+ assertProcStates(app, PROCESS_STATE_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ,
+ SCHED_GROUP_DEFAULT);
+ }
+
+ @SuppressWarnings("GuardedBy")
+ @Test
+ public void testUpdateOomAdj_DoOne_Service_Chain_BoundByFgService_Branch_3() {
+ ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+ MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
+ ProcessRecord client = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
+ MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
+ doReturn(mock(WindowProcessController.class)).when(client).getWindowProcessController();
+ WindowProcessController wpc = client.getWindowProcessController();
+ doReturn(true).when(wpc).isHomeProcess();
+ bindService(app, client, null, 0, mock(IBinder.class));
+ ProcessRecord client2 = spy(makeDefaultProcessRecord(MOCKAPP3_PID, MOCKAPP3_UID,
+ MOCKAPP3_PROCESSNAME, MOCKAPP3_PACKAGENAME, false));
+ bindService(app, client2, null, 0, mock(IBinder.class));
+ client2.setHasForegroundServices(true, 0);
+ ProcessRecord client3 = spy(makeDefaultProcessRecord(MOCKAPP4_PID, MOCKAPP4_UID,
+ MOCKAPP4_PROCESSNAME, MOCKAPP4_PACKAGENAME, false));
+ client3.forcingToImportant = new Object();
+ bindService(app, client3, null, 0, mock(IBinder.class));
+ sService.mWakefulness = PowerManagerInternal.WAKEFULNESS_AWAKE;
+ sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
+
+ assertProcStates(app, PROCESS_STATE_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ,
+ SCHED_GROUP_DEFAULT);
+ }
+
+ @SuppressWarnings("GuardedBy")
+ @Test
+ public void testUpdateOomAdj_DoOne_Service_Provider() {
+ ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+ MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
+ ProcessRecord client = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
+ MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
+ bindService(app, client, null, 0, mock(IBinder.class));
+ ProcessRecord client2 = spy(makeDefaultProcessRecord(MOCKAPP3_PID, MOCKAPP3_UID,
+ MOCKAPP3_PROCESSNAME, MOCKAPP3_PACKAGENAME, false));
+ bindProvider(client, client2, null, null, false);
+ client2.setHasForegroundServices(true, 0);
+ sService.mWakefulness = PowerManagerInternal.WAKEFULNESS_AWAKE;
+ sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
+
+ assertProcStates(app, PROCESS_STATE_BOUND_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ,
+ SCHED_GROUP_DEFAULT);
+ }
+
+ @SuppressWarnings("GuardedBy")
+ @Test
+ public void testUpdateOomAdj_DoOne_Service_Provider_Cycle() {
+ ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+ MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
+ ProcessRecord client = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
+ MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
+ bindService(app, client, null, 0, mock(IBinder.class));
+ ProcessRecord client2 = spy(makeDefaultProcessRecord(MOCKAPP3_PID, MOCKAPP3_UID,
+ MOCKAPP3_PROCESSNAME, MOCKAPP3_PACKAGENAME, false));
+ bindProvider(client, client2, null, null, false);
+ client2.setHasForegroundServices(true, 0);
+ bindService(client2, app, null, 0, mock(IBinder.class));
+ sService.mWakefulness = PowerManagerInternal.WAKEFULNESS_AWAKE;
+ sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
+
+ assertProcStates(app, PROCESS_STATE_BOUND_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ,
+ SCHED_GROUP_DEFAULT);
+ }
+
+ @SuppressWarnings("GuardedBy")
+ @Test
+ public void testUpdateOomAdj_DoOne_Provider_Chain_BoundByFgService() {
+ ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+ MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
+ ProcessRecord client = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
+ MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
+ bindProvider(app, client, null, null, false);
+ ProcessRecord client2 = spy(makeDefaultProcessRecord(MOCKAPP3_PID, MOCKAPP3_UID,
+ MOCKAPP3_PROCESSNAME, MOCKAPP3_PACKAGENAME, false));
+ bindProvider(client, client2, null, null, false);
+ client2.setHasForegroundServices(true, 0);
+ sService.mWakefulness = PowerManagerInternal.WAKEFULNESS_AWAKE;
+ sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
+
+ assertProcStates(app, PROCESS_STATE_BOUND_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ,
+ SCHED_GROUP_DEFAULT);
+ }
+
+ @SuppressWarnings("GuardedBy")
+ @Test
+ public void testUpdateOomAdj_DoOne_Provider_Chain_BoundByFgService_Cycle() {
+ ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+ MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
+ ProcessRecord client = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
+ MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
+ bindProvider(app, client, null, null, false);
+ ProcessRecord client2 = spy(makeDefaultProcessRecord(MOCKAPP3_PID, MOCKAPP3_UID,
+ MOCKAPP3_PROCESSNAME, MOCKAPP3_PACKAGENAME, false));
+ bindProvider(client, client2, null, null, false);
+ client2.setHasForegroundServices(true, 0);
+ bindProvider(client2, app, null, null, false);
+ sService.mWakefulness = PowerManagerInternal.WAKEFULNESS_AWAKE;
+ sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
+
+ assertProcStates(app, PROCESS_STATE_BOUND_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ,
+ SCHED_GROUP_DEFAULT);
+ }
+
+ @SuppressWarnings("GuardedBy")
+ @Test
+ public void testUpdateOomAdj_DoAll_Unbound() {
+ ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+ MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
+ app.forcingToImportant = new Object();
+ ProcessRecord app2 = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
+ MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
+ app2.setHasForegroundServices(true, 0);
+ ArrayList<ProcessRecord> lru = sService.mProcessList.mLruProcesses;
+ lru.clear();
+ lru.add(app);
+ lru.add(app2);
+ sService.mWakefulness = PowerManagerInternal.WAKEFULNESS_AWAKE;
+ sService.mOomAdjuster.updateOomAdjLocked(OomAdjuster.OOM_ADJ_REASON_NONE);
+ lru.clear();
+
+ assertProcStates(app, PROCESS_STATE_TRANSIENT_BACKGROUND, PERCEPTIBLE_APP_ADJ,
+ SCHED_GROUP_DEFAULT);
+ assertProcStates(app2, PROCESS_STATE_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ,
+ SCHED_GROUP_DEFAULT);
+ }
+
+ @SuppressWarnings("GuardedBy")
+ @Test
+ public void testUpdateOomAdj_DoAll_BoundFgService() {
+ ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+ MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
+ app.forcingToImportant = new Object();
+ ProcessRecord app2 = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
+ MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
+ app2.setHasForegroundServices(true, 0);
+ bindService(app, app2, null, 0, mock(IBinder.class));
+ ArrayList<ProcessRecord> lru = sService.mProcessList.mLruProcesses;
+ lru.clear();
+ lru.add(app);
+ lru.add(app2);
+ sService.mWakefulness = PowerManagerInternal.WAKEFULNESS_AWAKE;
+ sService.mOomAdjuster.updateOomAdjLocked(OomAdjuster.OOM_ADJ_REASON_NONE);
+ lru.clear();
+
+ assertProcStates(app, PROCESS_STATE_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ,
+ SCHED_GROUP_DEFAULT);
+ assertProcStates(app2, PROCESS_STATE_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ,
+ SCHED_GROUP_DEFAULT);
+ }
+
+ @SuppressWarnings("GuardedBy")
+ @Test
+ public void testUpdateOomAdj_DoAll_BoundFgService_Cycle() {
+ ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+ MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
+ ProcessRecord app2 = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
+ MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
+ bindService(app, app2, null, 0, mock(IBinder.class));
+ ProcessRecord app3 = spy(makeDefaultProcessRecord(MOCKAPP3_PID, MOCKAPP3_UID,
+ MOCKAPP3_PROCESSNAME, MOCKAPP3_PACKAGENAME, false));
+ bindService(app2, app3, null, 0, mock(IBinder.class));
+ app3.setHasForegroundServices(true, 0);
+ bindService(app3, app, null, 0, mock(IBinder.class));
+ ArrayList<ProcessRecord> lru = sService.mProcessList.mLruProcesses;
+ lru.clear();
+ lru.add(app);
+ lru.add(app2);
+ lru.add(app3);
+ sService.mWakefulness = PowerManagerInternal.WAKEFULNESS_AWAKE;
+ sService.mOomAdjuster.updateOomAdjLocked(OomAdjuster.OOM_ADJ_REASON_NONE);
+ lru.clear();
+
+ assertProcStates(app, PROCESS_STATE_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ,
+ SCHED_GROUP_DEFAULT);
+ assertProcStates(app2, PROCESS_STATE_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ,
+ SCHED_GROUP_DEFAULT);
+ assertProcStates(app3, PROCESS_STATE_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ,
+ SCHED_GROUP_DEFAULT);
+ }
+
+ @SuppressWarnings("GuardedBy")
+ @Test
+ public void testUpdateOomAdj_DoAll_BoundFgService_Cycle_Branch_2() {
+ ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+ MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
+ ProcessRecord app2 = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
+ MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
+ ServiceRecord s = bindService(app, app2, null, 0, mock(IBinder.class));
+ ProcessRecord app3 = spy(makeDefaultProcessRecord(MOCKAPP3_PID, MOCKAPP3_UID,
+ MOCKAPP3_PROCESSNAME, MOCKAPP3_PACKAGENAME, false));
+ bindService(app2, app3, null, 0, mock(IBinder.class));
+ bindService(app3, app, null, 0, mock(IBinder.class));
+ doReturn(mock(WindowProcessController.class)).when(app3).getWindowProcessController();
+ WindowProcessController wpc = app3.getWindowProcessController();
+ doReturn(true).when(wpc).isHomeProcess();
+ ProcessRecord app4 = spy(makeDefaultProcessRecord(MOCKAPP4_PID, MOCKAPP4_UID,
+ MOCKAPP4_PROCESSNAME, MOCKAPP4_PACKAGENAME, false));
+ app4.setHasOverlayUi(true);
+ bindService(app, app4, s, 0, mock(IBinder.class));
+ ProcessRecord app5 = spy(makeDefaultProcessRecord(MOCKAPP5_PID, MOCKAPP5_UID,
+ MOCKAPP5_PROCESSNAME, MOCKAPP5_PACKAGENAME, false));
+ app5.setHasForegroundServices(true, 0);
+ bindService(app, app5, s, 0, mock(IBinder.class));
+ ArrayList<ProcessRecord> lru = sService.mProcessList.mLruProcesses;
+ lru.clear();
+ lru.add(app);
+ lru.add(app2);
+ lru.add(app3);
+ lru.add(app4);
+ lru.add(app5);
+ sService.mWakefulness = PowerManagerInternal.WAKEFULNESS_AWAKE;
+ sService.mOomAdjuster.updateOomAdjLocked(OomAdjuster.OOM_ADJ_REASON_NONE);
+ lru.clear();
+
+ assertProcStates(app, PROCESS_STATE_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ,
+ SCHED_GROUP_DEFAULT);
+ assertProcStates(app2, PROCESS_STATE_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ,
+ SCHED_GROUP_DEFAULT);
+ assertProcStates(app3, PROCESS_STATE_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ,
+ SCHED_GROUP_DEFAULT);
+ assertProcStates(app4, PROCESS_STATE_IMPORTANT_FOREGROUND, PERCEPTIBLE_APP_ADJ,
+ SCHED_GROUP_DEFAULT);
+ assertProcStates(app5, PROCESS_STATE_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ,
+ SCHED_GROUP_DEFAULT);
+ }
+
+ @SuppressWarnings("GuardedBy")
+ @Test
+ public void testUpdateOomAdj_DoAll_BoundFgService_Cycle_Branch_3() {
+ ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+ MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
+ ProcessRecord app2 = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
+ MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
+ ServiceRecord s = bindService(app, app2, null, 0, mock(IBinder.class));
+ ProcessRecord app3 = spy(makeDefaultProcessRecord(MOCKAPP3_PID, MOCKAPP3_UID,
+ MOCKAPP3_PROCESSNAME, MOCKAPP3_PACKAGENAME, false));
+ bindService(app2, app3, null, 0, mock(IBinder.class));
+ bindService(app3, app, null, 0, mock(IBinder.class));
+ doReturn(mock(WindowProcessController.class)).when(app3).getWindowProcessController();
+ WindowProcessController wpc = app3.getWindowProcessController();
+ doReturn(true).when(wpc).isHomeProcess();
+ ProcessRecord app4 = spy(makeDefaultProcessRecord(MOCKAPP4_PID, MOCKAPP4_UID,
+ MOCKAPP4_PROCESSNAME, MOCKAPP4_PACKAGENAME, false));
+ app4.setHasOverlayUi(true);
+ bindService(app, app4, s, 0, mock(IBinder.class));
+ ProcessRecord app5 = spy(makeDefaultProcessRecord(MOCKAPP5_PID, MOCKAPP5_UID,
+ MOCKAPP5_PROCESSNAME, MOCKAPP5_PACKAGENAME, false));
+ app5.setHasForegroundServices(true, 0);
+ bindService(app, app5, s, 0, mock(IBinder.class));
+ ArrayList<ProcessRecord> lru = sService.mProcessList.mLruProcesses;
+ lru.clear();
+ lru.add(app5);
+ lru.add(app4);
+ lru.add(app3);
+ lru.add(app2);
+ lru.add(app);
+ sService.mWakefulness = PowerManagerInternal.WAKEFULNESS_AWAKE;
+ sService.mOomAdjuster.updateOomAdjLocked(OomAdjuster.OOM_ADJ_REASON_NONE);
+ lru.clear();
+
+ assertProcStates(app, PROCESS_STATE_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ,
+ SCHED_GROUP_DEFAULT);
+ assertProcStates(app2, PROCESS_STATE_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ,
+ SCHED_GROUP_DEFAULT);
+ assertProcStates(app3, PROCESS_STATE_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ,
+ SCHED_GROUP_DEFAULT);
+ assertProcStates(app4, PROCESS_STATE_IMPORTANT_FOREGROUND, PERCEPTIBLE_APP_ADJ,
+ SCHED_GROUP_DEFAULT);
+ assertProcStates(app5, PROCESS_STATE_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ,
+ SCHED_GROUP_DEFAULT);
+ }
+
+ @SuppressWarnings("GuardedBy")
+ @Test
+ public void testUpdateOomAdj_DoAll_BoundFgService_Cycle_Branch_4() {
+ ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+ MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
+ ProcessRecord app2 = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
+ MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
+ ServiceRecord s = bindService(app, app2, null, 0, mock(IBinder.class));
+ ProcessRecord app3 = spy(makeDefaultProcessRecord(MOCKAPP3_PID, MOCKAPP3_UID,
+ MOCKAPP3_PROCESSNAME, MOCKAPP3_PACKAGENAME, false));
+ bindService(app2, app3, null, 0, mock(IBinder.class));
+ bindService(app3, app, null, 0, mock(IBinder.class));
+ doReturn(mock(WindowProcessController.class)).when(app3).getWindowProcessController();
+ WindowProcessController wpc = app3.getWindowProcessController();
+ doReturn(true).when(wpc).isHomeProcess();
+ ProcessRecord app4 = spy(makeDefaultProcessRecord(MOCKAPP4_PID, MOCKAPP4_UID,
+ MOCKAPP4_PROCESSNAME, MOCKAPP4_PACKAGENAME, false));
+ app4.setHasOverlayUi(true);
+ bindService(app, app4, s, 0, mock(IBinder.class));
+ ProcessRecord app5 = spy(makeDefaultProcessRecord(MOCKAPP5_PID, MOCKAPP5_UID,
+ MOCKAPP5_PROCESSNAME, MOCKAPP5_PACKAGENAME, false));
+ app5.setHasForegroundServices(true, 0);
+ bindService(app, app5, s, 0, mock(IBinder.class));
+ ArrayList<ProcessRecord> lru = sService.mProcessList.mLruProcesses;
+ lru.clear();
+ lru.add(app3);
+ lru.add(app4);
+ lru.add(app2);
+ lru.add(app);
+ lru.add(app5);
+ sService.mWakefulness = PowerManagerInternal.WAKEFULNESS_AWAKE;
+ sService.mOomAdjuster.updateOomAdjLocked(OomAdjuster.OOM_ADJ_REASON_NONE);
+ lru.clear();
+
+ assertProcStates(app, PROCESS_STATE_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ,
+ SCHED_GROUP_DEFAULT);
+ assertProcStates(app2, PROCESS_STATE_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ,
+ SCHED_GROUP_DEFAULT);
+ assertProcStates(app3, PROCESS_STATE_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ,
+ SCHED_GROUP_DEFAULT);
+ assertProcStates(app4, PROCESS_STATE_IMPORTANT_FOREGROUND, PERCEPTIBLE_APP_ADJ,
+ SCHED_GROUP_DEFAULT);
+ assertProcStates(app5, PROCESS_STATE_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ,
+ SCHED_GROUP_DEFAULT);
+ }
+
+ @SuppressWarnings("GuardedBy")
+ @Test
+ public void testUpdateOomAdj_DoAll_Provider_Cycle_Branch_2() {
+ ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+ MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
+ ProcessRecord app2 = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
+ MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
+ ContentProviderRecord cr = bindProvider(app, app2, null, null, false);
+ ProcessRecord app3 = spy(makeDefaultProcessRecord(MOCKAPP3_PID, MOCKAPP3_UID,
+ MOCKAPP3_PROCESSNAME, MOCKAPP3_PACKAGENAME, false));
+ bindProvider(app2, app3, null, null, false);
+ bindProvider(app3, app, null, null, false);
+ doReturn(mock(WindowProcessController.class)).when(app3).getWindowProcessController();
+ WindowProcessController wpc = app3.getWindowProcessController();
+ doReturn(true).when(wpc).isHomeProcess();
+ ProcessRecord app4 = spy(makeDefaultProcessRecord(MOCKAPP4_PID, MOCKAPP4_UID,
+ MOCKAPP4_PROCESSNAME, MOCKAPP4_PACKAGENAME, false));
+ app4.setHasOverlayUi(true);
+ bindProvider(app, app4, cr, null, false);
+ ProcessRecord app5 = spy(makeDefaultProcessRecord(MOCKAPP5_PID, MOCKAPP5_UID,
+ MOCKAPP5_PROCESSNAME, MOCKAPP5_PACKAGENAME, false));
+ app5.setHasForegroundServices(true, 0);
+ bindProvider(app, app5, cr, null, false);
+ ArrayList<ProcessRecord> lru = sService.mProcessList.mLruProcesses;
+ lru.clear();
+ lru.add(app);
+ lru.add(app2);
+ lru.add(app3);
+ lru.add(app4);
+ lru.add(app5);
+ sService.mWakefulness = PowerManagerInternal.WAKEFULNESS_AWAKE;
+ sService.mOomAdjuster.updateOomAdjLocked(OomAdjuster.OOM_ADJ_REASON_NONE);
+ lru.clear();
+
+ assertProcStates(app, PROCESS_STATE_BOUND_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ,
+ SCHED_GROUP_DEFAULT);
+ assertProcStates(app2, PROCESS_STATE_BOUND_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ,
+ SCHED_GROUP_DEFAULT);
+ assertProcStates(app3, PROCESS_STATE_BOUND_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ,
+ SCHED_GROUP_DEFAULT);
+ assertProcStates(app4, PROCESS_STATE_IMPORTANT_FOREGROUND, PERCEPTIBLE_APP_ADJ,
+ SCHED_GROUP_DEFAULT);
+ assertProcStates(app5, PROCESS_STATE_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ,
+ SCHED_GROUP_DEFAULT);
+ }
+
+ private ProcessRecord makeDefaultProcessRecord(int pid, int uid, String processName,
+ String packageName, boolean hasShownUi) {
+ long now = SystemClock.uptimeMillis();
+ return makeProcessRecord(sService, pid, uid, processName,
+ packageName, 12345, Build.VERSION_CODES.CUR_DEVELOPMENT,
+ now, now, now, 12345, UNKNOWN_ADJ, UNKNOWN_ADJ,
+ UNKNOWN_ADJ, CACHED_APP_MAX_ADJ,
+ SCHED_GROUP_DEFAULT, SCHED_GROUP_DEFAULT,
+ PROCESS_STATE_NONEXISTENT, PROCESS_STATE_NONEXISTENT,
+ PROCESS_STATE_NONEXISTENT, PROCESS_STATE_NONEXISTENT,
+ 0, 0, false, false, false, ServiceInfo.FOREGROUND_SERVICE_TYPE_NONE,
+ false, false, false, hasShownUi, false, false, false, false, false, false, null,
+ 0, 0, 0, true, 0, null, false);
+ }
+
+ private ProcessRecord makeProcessRecord(ActivityManagerService service, int pid, int uid,
+ String processName, String packageName, long versionCode, int targetSdkVersion,
+ long lastActivityTime, long lastPssTime, long nextPssTime, long lastPss, int maxAdj,
+ int setRawAdj, int curAdj, int setAdj, int curSchedGroup, int setSchedGroup,
+ int curProcState, int repProcState, int curRawProcState, int setProcState,
+ int connectionGroup, int connectionImportance, boolean serviceb,
+ boolean hasClientActivities, boolean hasForegroundServices, int fgServiceTypes,
+ boolean hasForegroundActivities, boolean repForegroundActivities, boolean systemNoUi,
+ boolean hasShownUi, boolean hasTopUi, boolean hasOverlayUi,
+ boolean runningRemoteAnimation, boolean hasAboveClient, boolean treatLikeActivity,
+ boolean killedByAm, Object forcingToImportant, int numOfCurReceivers,
+ long lastProviderTime, long lastTopTime, boolean cached, int numOfExecutingServices,
+ String isolatedEntryPoint, boolean execServicesFg) {
+ ApplicationInfo ai = spy(new ApplicationInfo());
+ ai.uid = uid;
+ ai.packageName = packageName;
+ ai.longVersionCode = versionCode;
+ ai.targetSdkVersion = targetSdkVersion;
+ ProcessRecord app = new ProcessRecord(service, ai, processName, uid);
+ app.thread = mock(IApplicationThread.class);
+ app.lastActivityTime = lastActivityTime;
+ app.lastPssTime = lastPssTime;
+ app.nextPssTime = nextPssTime;
+ app.lastPss = lastPss;
+ app.maxAdj = maxAdj;
+ app.setRawAdj = setRawAdj;
+ app.curAdj = curAdj;
+ app.setAdj = setAdj;
+ app.setCurrentSchedulingGroup(curSchedGroup);
+ app.setSchedGroup = setSchedGroup;
+ app.setCurProcState(curProcState);
+ app.setReportedProcState(repProcState);
+ app.setCurRawProcState(curRawProcState);
+ app.setProcState = setProcState;
+ app.connectionGroup = connectionGroup;
+ app.connectionImportance = connectionImportance;
+ app.serviceb = serviceb;
+ app.setHasClientActivities(hasClientActivities);
+ app.setHasForegroundServices(hasForegroundServices, fgServiceTypes);
+ app.setHasClientActivities(hasForegroundActivities);
+ app.repForegroundActivities = repForegroundActivities;
+ app.systemNoUi = systemNoUi;
+ app.hasShownUi = hasShownUi;
+ app.setHasTopUi(hasTopUi);
+ app.setHasOverlayUi(hasOverlayUi);
+ app.runningRemoteAnimation = runningRemoteAnimation;
+ app.hasAboveClient = hasAboveClient;
+ app.treatLikeActivity = treatLikeActivity;
+ app.killedByAm = killedByAm;
+ app.forcingToImportant = forcingToImportant;
+ for (int i = 0; i < numOfCurReceivers; i++) {
+ app.curReceivers.add(mock(BroadcastRecord.class));
+ }
+ app.lastProviderTime = lastProviderTime;
+ app.lastTopTime = lastTopTime;
+ app.cached = cached;
+ for (int i = 0; i < numOfExecutingServices; i++) {
+ app.executingServices.add(mock(ServiceRecord.class));
+ }
+ app.isolatedEntryPoint = isolatedEntryPoint;
+ app.execServicesFg = execServicesFg;
+ return app;
+ }
+
+ private ServiceRecord bindService(ProcessRecord service, ProcessRecord client,
+ ServiceRecord record, int bindFlags, IBinder binder) {
+ if (record == null) {
+ record = mock(ServiceRecord.class);
+ record.app = service;
+ setFieldValue(ServiceRecord.class, record, "connections",
+ new ArrayMap<IBinder, ArrayList<ConnectionRecord>>());
+ service.services.add(record);
+ doCallRealMethod().when(record).getConnections();
+ }
+ AppBindRecord binding = new AppBindRecord(record, null, client);
+ ConnectionRecord cr = spy(new ConnectionRecord(binding,
+ mock(ActivityServiceConnectionsHolder.class),
+ mock(IServiceConnection.class), bindFlags,
+ 0, null, client.uid, client.processName, client.info.packageName));
+ doCallRealMethod().when(record).addConnection(any(IBinder.class),
+ any(ConnectionRecord.class));
+ record.addConnection(binder, cr);
+ client.connections.add(cr);
+ binding.connections.add(cr);
+ doNothing().when(cr).trackProcState(anyInt(), anyInt(), anyLong());
+ return record;
+ }
+
+ private ContentProviderRecord bindProvider(ProcessRecord publisher, ProcessRecord client,
+ ContentProviderRecord record, String name, boolean hasExternalProviders) {
+ if (record == null) {
+ record = mock(ContentProviderRecord.class);
+ publisher.pubProviders.put(name, record);
+ record.proc = publisher;
+ setFieldValue(ContentProviderRecord.class, record, "connections",
+ new ArrayList<ContentProviderConnection>());
+ doReturn(hasExternalProviders).when(record).hasExternalProcessHandles();
+ }
+ ContentProviderConnection conn = spy(new ContentProviderConnection(record, client,
+ client.info.packageName));
+ record.connections.add(conn);
+ client.conProviders.add(conn);
+ return record;
+ }
+
+ private void assertProcStates(ProcessRecord app, int expectedProcState, int expectedAdj,
+ int expectedSchedGroup) {
+ assertEquals(expectedProcState, app.setProcState);
+ assertEquals(expectedAdj, app.setAdj);
+ assertEquals(expectedSchedGroup, app.setSchedGroup);
+ }
+}
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 8a1f046..29244f0 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java
@@ -133,7 +133,7 @@
mHandlerThread = new HandlerThread(TAG);
mHandlerThread.start();
mHandler = new TestHandler(mHandlerThread.getLooper());
- mInjector = new TestInjector();
+ mInjector = new TestInjector(mContext);
mAms = new ActivityManagerService(mInjector, mServiceThreadRule.getThread());
mAms.mWaitForNetworkTimeoutMs = 2000;
mAms.mActivityTaskManager = new ActivityTaskManagerService(mContext);
@@ -920,9 +920,8 @@
private class TestInjector extends Injector {
private boolean mRestricted = true;
- @Override
- public Context getContext() {
- return mContext;
+ TestInjector(Context context) {
+ super(context);
}
@Override
diff --git a/services/tests/servicestests/src/com/android/server/am/AppErrorDialogTest.java b/services/tests/servicestests/src/com/android/server/am/AppErrorDialogTest.java
index 87cc0ff..377bfd1 100644
--- a/services/tests/servicestests/src/com/android/server/am/AppErrorDialogTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/AppErrorDialogTest.java
@@ -51,7 +51,7 @@
@Before
public void setUp() throws Exception {
mContext = getInstrumentation().getTargetContext();
- mService = new ActivityManagerService(new ActivityManagerService.Injector() {
+ mService = new ActivityManagerService(new ActivityManagerService.Injector(mContext) {
@Override
public AppOpsService getAppOpsService(File file, Handler handler) {
return null;
@@ -66,11 +66,6 @@
public boolean isNetworkRestrictedForUid(int uid) {
return false;
}
-
- @Override
- public Context getContext() {
- return mContext;
- }
}, mServiceThreadRule.getThread());
mService.mActivityTaskManager = new ActivityTaskManagerService(mContext);
mService.mActivityTaskManager.initialize(null, null, mContext.getMainLooper());
diff --git a/services/tests/servicestests/src/com/android/server/am/CoreSettingsObserverTest.java b/services/tests/servicestests/src/com/android/server/am/CoreSettingsObserverTest.java
index 1eb02ad..4221575 100644
--- a/services/tests/servicestests/src/com/android/server/am/CoreSettingsObserverTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/CoreSettingsObserverTest.java
@@ -23,9 +23,11 @@
import static com.google.common.truth.Truth.assertWithMessage;
import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import android.content.Context;
+import android.content.res.Resources;
import android.os.Bundle;
import android.os.Handler;
import android.provider.Settings;
@@ -92,8 +94,10 @@
mContentResolver = new MockContentResolver(mContext);
mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
when(mContext.getContentResolver()).thenReturn(mContentResolver);
+ when(mContext.getResources()).thenReturn(mock(Resources.class));
- mAms = new ActivityManagerService(new TestInjector(), mServiceThreadRule.getThread());
+ mAms = new ActivityManagerService(new TestInjector(mContext),
+ mServiceThreadRule.getThread());
mCoreSettingsObserver = new CoreSettingsObserver(mAms);
}
@@ -158,9 +162,9 @@
}
private class TestInjector extends Injector {
- @Override
- public Context getContext() {
- return getInstrumentation().getContext();
+
+ TestInjector(Context context) {
+ super(context);
}
@Override
diff --git a/services/tests/servicestests/src/com/android/server/backup/TrampolineTest.java b/services/tests/servicestests/src/com/android/server/backup/TrampolineTest.java
index 3da2fd3..8668a3c 100644
--- a/services/tests/servicestests/src/com/android/server/backup/TrampolineTest.java
+++ b/services/tests/servicestests/src/com/android/server/backup/TrampolineTest.java
@@ -22,6 +22,7 @@
import static junit.framework.Assert.assertTrue;
import static junit.framework.Assert.fail;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
@@ -70,6 +71,7 @@
import java.io.FileDescriptor;
import java.io.IOException;
import java.io.PrintWriter;
+import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
@@ -227,7 +229,9 @@
trampoline.getBackupHandler().post(unlocked::open);
unlocked.block();
assertNull(trampoline.getUserService(NON_USER_SYSTEM));
- verify(mBackupManagerServiceMock, never()).startServiceForUser(NON_USER_SYSTEM);
+ //noinspection unchecked
+ verify(mBackupManagerServiceMock, never()).startServiceForUser(
+ eq(NON_USER_SYSTEM), any(Set.class));
}
@Test
@@ -752,17 +756,7 @@
}
@Test
- public void getTransportWhitelist_forwarded() {
- when(mBackupManagerServiceMock.getTransportWhitelist()).thenReturn(TRANSPORTS);
-
- assertEquals(TRANSPORTS, mTrampoline.getTransportWhitelist());
- verify(mBackupManagerServiceMock).getTransportWhitelist();
- }
-
- @Test
public void updateTransportAttributesForUser_forwarded() {
- when(mBackupManagerServiceMock.getTransportWhitelist()).thenReturn(TRANSPORTS);
-
mTrampoline.updateTransportAttributesForUser(
mUserId,
TRANSPORT_COMPONENT_NAME,
diff --git a/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java b/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
index f4a6231..4ffcf8f 100644
--- a/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
+++ b/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
@@ -39,6 +39,7 @@
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import static org.junit.Assume.assumeTrue;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Mockito.doReturn;
@@ -297,9 +298,6 @@
mInjector.setDisplayOn(true);
setChargingState(controller, false);
controller.checkIdleStates(USER_ID);
- assertEquals(STANDBY_BUCKET_EXEMPTED,
- controller.getAppStandbyBucket(PACKAGE_EXEMPTED_1, USER_ID,
- mInjector.mElapsedRealtime, false));
assertNotEquals(STANDBY_BUCKET_EXEMPTED,
controller.getAppStandbyBucket(PACKAGE_1, USER_ID,
mInjector.mElapsedRealtime, false));
@@ -378,6 +376,14 @@
}
@Test
+ public void testBoundWidgetPackageExempt() throws Exception {
+ assumeTrue(mInjector.getContext().getSystemService(AppWidgetManager.class) != null);
+ assertEquals(STANDBY_BUCKET_EXEMPTED,
+ mController.getAppStandbyBucket(PACKAGE_EXEMPTED_1, USER_ID,
+ mInjector.mElapsedRealtime, false));
+ }
+
+ @Test
public void testCharging() throws Exception {
long startTime;
TestParoleListener paroleListener = new TestParoleListener();
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 ecf3acd..ab2da2b 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java
@@ -98,7 +98,7 @@
new DexmakerShareClassLoaderRule();
final Context mContext = getInstrumentation().getTargetContext();
- final TestInjector mTestInjector = new TestInjector();
+ final TestInjector mTestInjector = new TestInjector(mContext);
ActivityTaskManagerService mService;
RootActivityContainer mRootActivityContainer;
@@ -467,6 +467,7 @@
spyOn(getLifecycleManager());
spyOn(getLockTaskController());
+ spyOn(getTaskChangeNotificationController());
doReturn(mock(IPackageManager.class)).when(this).getPackageManager();
// allow background activity starts by default
doReturn(true).when(this).isBackgroundActivityStartsEnabled();
@@ -567,9 +568,8 @@
private static class TestInjector extends ActivityManagerService.Injector {
private ServiceThread mHandlerThread;
- @Override
- public Context getContext() {
- return getInstrumentation().getTargetContext();
+ TestInjector(Context context) {
+ super(context);
}
@Override
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 a1999c90..b7a85d7 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
@@ -43,6 +43,8 @@
import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
import static java.lang.Integer.MAX_VALUE;
@@ -900,6 +902,46 @@
true /* showRecents */));
}
+ @Test
+ public void addTask_callsTaskNotificationController() {
+ final TaskRecord task = createTaskBuilder(".Task").build();
+
+ mRecentTasks.add(task);
+ mRecentTasks.remove(task);
+
+ TaskChangeNotificationController controller =
+ mTestService.getTaskChangeNotificationController();
+ verify(controller, times(2)).notifyTaskListUpdated();
+ }
+
+ @Test
+ public void removeTask_callsTaskNotificationController() {
+ final TaskRecord task = createTaskBuilder(".Task").build();
+
+ mRecentTasks.add(task);
+ mRecentTasks.remove(task);
+
+ // 2 calls - Once for add and once for remove
+ TaskChangeNotificationController controller =
+ mTestService.getTaskChangeNotificationController();
+ verify(controller, times(2)).notifyTaskListUpdated();
+ }
+
+ @Test
+ public void removeALlVisibleTask_callsTaskNotificationController_twice() {
+ final TaskRecord task1 = createTaskBuilder(".Task").build();
+ final TaskRecord task2 = createTaskBuilder(".Task2").build();
+
+ mRecentTasks.add(task1);
+ mRecentTasks.add(task2);
+ mRecentTasks.removeAllVisibleTasks(TEST_USER_0_ID);
+
+ // 4 calls - Twice for add and twice for remove
+ TaskChangeNotificationController controller =
+ mTestService.getTaskChangeNotificationController();
+ verify(controller, times(4)).notifyTaskListUpdated();
+ }
+
/**
* Ensures that the raw recent tasks list is in the provided order. Note that the expected tasks
* should be ordered from least to most recent.
diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java
index cd292b2..f5a1d75 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java
@@ -44,6 +44,7 @@
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
+import android.app.ActivityManager.TaskSnapshot;
import android.os.Binder;
import android.os.IInterface;
import android.platform.test.annotations.Presubmit;
@@ -73,6 +74,7 @@
@Mock OnAnimationFinishedCallback mFinishedCallback;
@Mock IRecentsAnimationRunner mMockRunner;
@Mock RecentsAnimationController.RecentsAnimationCallbacks mAnimationCallbacks;
+ @Mock TaskSnapshot mMockTaskSnapshot;
private RecentsAnimationController mController;
@Before
@@ -104,7 +106,7 @@
// Verify that the finish callback to reparent the leash is called
verify(mFinishedCallback).onAnimationFinished(eq(adapter));
// Verify the animation canceled callback to the app was made
- verify(mMockRunner).onAnimationCanceled(false);
+ verify(mMockRunner).onAnimationCanceled(null /* taskSnapshot */);
verifyNoMoreInteractionsExceptAsBinder(mMockRunner);
}
@@ -162,7 +164,7 @@
mController.setDeferredCancel(true /* deferred */, false /* screenshot */);
mController.cancelAnimationWithScreenshot(false /* screenshot */);
- verify(mMockRunner).onAnimationCanceled(false /* deferredWithScreenshot */);
+ verify(mMockRunner).onAnimationCanceled(null /* taskSnapshot */);
assertNull(mController.mRecentScreenshotAnimator);
// Simulate the app transition finishing
@@ -183,9 +185,14 @@
mController.addAnimation(appWindow.getTask(), false /* isRecentTaskInvisible */);
assertTrue(mController.isAnimatingTask(appWindow.getTask()));
+ spyOn(mWm.mTaskSnapshotController);
+ doNothing().when(mWm.mTaskSnapshotController).notifyAppVisibilityChanged(any(),
+ anyBoolean());
+ doReturn(mMockTaskSnapshot).when(mWm.mTaskSnapshotController).getSnapshot(anyInt(),
+ anyInt(), eq(false) /* restoreFromDisk */, eq(false) /* reducedResolution */);
mController.setDeferredCancel(true /* deferred */, true /* screenshot */);
mController.cancelAnimationWithScreenshot(true /* screenshot */);
- verify(mMockRunner).onAnimationCanceled(true /* deferredWithScreenshot */);
+ verify(mMockRunner).onAnimationCanceled(mMockTaskSnapshot /* taskSnapshot */);
assertNotNull(mController.mRecentScreenshotAnimator);
assertTrue(mController.mRecentScreenshotAnimator.isAnimating());
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index 2298aa1..2bdeddf 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -830,6 +830,9 @@
mUserState.get(user).dumpDatabaseInfo(ipw);
}
return;
+ } else if ("appstandby".equals(arg)) {
+ mAppStandby.dumpState(args, pw);
+ return;
} else if (arg != null && !arg.startsWith("-")) {
// Anything else that doesn't start with '-' is a pkg to filter
pkg = arg;
diff --git a/telecomm/java/android/telecom/Logging/Session.java b/telecomm/java/android/telecom/Logging/Session.java
index 50c3cd9..95a47e1 100644
--- a/telecomm/java/android/telecom/Logging/Session.java
+++ b/telecomm/java/android/telecom/Logging/Session.java
@@ -33,6 +33,8 @@
*/
public class Session {
+ public static final String LOG_TAG = "Session";
+
public static final String START_SESSION = "START_SESSION";
public static final String START_EXTERNAL_SESSION = "START_EXTERNAL_SESSION";
public static final String CREATE_SUBSESSION = "CREATE_SUBSESSION";
@@ -45,6 +47,9 @@
public static final String EXTERNAL_INDICATOR = "E-";
public static final String TRUNCATE_STRING = "...";
+ // Prevent infinite recursion by setting a reasonable limit.
+ private static final int SESSION_RECURSION_LIMIT = 25;
+
/**
* Initial value of mExecutionEndTimeMs and the final value of {@link #getLocalExecutionTime()}
* if the Session is canceled.
@@ -226,6 +231,15 @@
// Builds full session id recursively
private String getFullSessionId() {
+ return getFullSessionId(0);
+ }
+
+ // keep track of calls and bail if we hit the recursion limit
+ private String getFullSessionId(int parentCount) {
+ if (parentCount >= SESSION_RECURSION_LIMIT) {
+ Log.w(LOG_TAG, "getFullSessionId: Hit recursion limit!");
+ return TRUNCATE_STRING + mSessionId;
+ }
// Cache mParentSession locally to prevent a concurrency problem where
// Log.endParentSessions() is called while a logging statement is running (Log.i, for
// example) and setting mParentSession to null in a different thread after the null check
@@ -235,42 +249,57 @@
return mSessionId;
} else {
if (Log.VERBOSE) {
- return parentSession.getFullSessionId() +
+ return parentSession.getFullSessionId(parentCount + 1)
// Append "_X" to subsession to show subsession designation.
- SESSION_SEPARATION_CHAR_CHILD + mSessionId;
+ + SESSION_SEPARATION_CHAR_CHILD + mSessionId;
} else {
// Only worry about the base ID at the top of the tree.
- return parentSession.getFullSessionId();
+ return parentSession.getFullSessionId(parentCount + 1);
}
}
}
- // Print out the full Session tree from any subsession node
- public String printFullSessionTree() {
- // Get to the top of the tree
+ private Session getRootSession(String callingMethod) {
+ int currParentCount = 0;
Session topNode = this;
while (topNode.getParentSession() != null) {
+ if (currParentCount >= SESSION_RECURSION_LIMIT) {
+ Log.w(LOG_TAG, "getRootSession: Hit recursion limit from " + callingMethod);
+ break;
+ }
topNode = topNode.getParentSession();
+ currParentCount++;
}
- return topNode.printSessionTree();
+ return topNode;
+ }
+
+ // Print out the full Session tree from any subsession node
+ public String printFullSessionTree() {
+ return getRootSession("printFullSessionTree").printSessionTree();
}
// Recursively move down session tree using DFS, but print out each node when it is reached.
- public String printSessionTree() {
+ private String printSessionTree() {
StringBuilder sb = new StringBuilder();
- printSessionTree(0, sb);
+ printSessionTree(0, sb, 0);
return sb.toString();
}
- private void printSessionTree(int tabI, StringBuilder sb) {
+ private void printSessionTree(int tabI, StringBuilder sb, int currChildCount) {
+ // Prevent infinite recursion.
+ if (currChildCount >= SESSION_RECURSION_LIMIT) {
+ Log.w(LOG_TAG, "printSessionTree: Hit recursion limit!");
+ sb.append(TRUNCATE_STRING);
+ return;
+ }
sb.append(toString());
for (Session child : mChildSessions) {
sb.append("\n");
for (int i = 0; i <= tabI; i++) {
sb.append("\t");
}
- child.printSessionTree(tabI + 1, sb);
+ child.printSessionTree(tabI + 1, sb, currChildCount + 1);
}
}
@@ -279,11 +308,17 @@
// recent) will be truncated to "..."
public String getFullMethodPath(boolean truncatePath) {
StringBuilder sb = new StringBuilder();
- getFullMethodPath(sb, truncatePath);
+ getFullMethodPath(sb, truncatePath, 0);
return sb.toString();
}
- private synchronized void getFullMethodPath(StringBuilder sb, boolean truncatePath) {
+ private synchronized void getFullMethodPath(StringBuilder sb, boolean truncatePath,
+ int parentCount) {
+ if (parentCount >= SESSION_RECURSION_LIMIT) {
+ Log.w(LOG_TAG, "getFullMethodPath: Hit recursion limit!");
+ sb.append(TRUNCATE_STRING);
+ return;
+ }
// Return cached value for method path. When returning the truncated path, recalculate the
// full path without using the cached value.
if (!TextUtils.isEmpty(mFullMethodPathCache) && !truncatePath) {
@@ -296,7 +331,7 @@
// Check to see if the session has been renamed yet. If it has not, then the session
// has not been continued.
isSessionStarted = !mShortMethodName.equals(parentSession.mShortMethodName);
- parentSession.getFullMethodPath(sb, truncatePath);
+ parentSession.getFullMethodPath(sb, truncatePath, parentCount + 1);
sb.append(SUBSESSION_SEPARATION_CHAR);
}
// Encapsulate the external session's method name so it is obvious what part of the session
@@ -319,13 +354,10 @@
mFullMethodPathCache = sb.toString();
}
}
+
// Recursively move to the top of the tree to see if the parent session is external.
private boolean isSessionExternal() {
- if (getParentSession() == null) {
- return isExternal();
- } else {
- return getParentSession().isSessionExternal();
- }
+ return getRootSession("isSessionExternal").isExternal();
}
@Override
diff --git a/telephony/java/android/provider/Telephony.java b/telephony/java/android/provider/Telephony.java
index 17d725e..c4a9ee9 100644
--- a/telephony/java/android/provider/Telephony.java
+++ b/telephony/java/android/provider/Telephony.java
@@ -24,7 +24,6 @@
import android.annotation.SystemApi;
import android.annotation.TestApi;
import android.annotation.UnsupportedAppUsage;
-import android.app.job.JobService;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.ContentValues;
@@ -4102,9 +4101,11 @@
* ServiceState provider.
* <p>
* Use this {@link Uri} with a {@link ContentObserver} to be notified of changes to the
- * {@link ServiceState} while your app is running. You can also use a {@link JobService} to
+ * {@link ServiceState} while your app is running.
+ * You can also use a {@link android.app.job.JobService} to
* ensure your app is notified of changes to the {@link Uri} even when it is not running.
- * Note, however, that using a {@link JobService} does not guarantee timely delivery of
+ * Note, however, that using a {@link android.app.job.JobService}
+ * does not guarantee timely delivery of
* updates to the {@link Uri}.
*
* @param subscriptionId the subscriptionId to receive updates on
@@ -4121,9 +4122,11 @@
* ServiceState provider.
* <p>
* Use this {@link Uri} with a {@link ContentObserver} to be notified of changes to the
- * {@link ServiceState} while your app is running. You can also use a {@link JobService} to
+ * {@link ServiceState} while your app is running. You can also use a
+ * {@link android.app.job.JobService} to
* ensure your app is notified of changes to the {@link Uri} even when it is not running.
- * Note, however, that using a {@link JobService} does not guarantee timely delivery of
+ * Note, however, that using a {@link android.app.job.JobService}
+ * does not guarantee timely delivery of
* updates to the {@link Uri}.
*
* @param subscriptionId the subscriptionId to receive updates on
@@ -4378,10 +4381,11 @@
* <p>
* Use this {@link Uri} with a {@link ContentObserver} to be notified of changes to the
* carrier identity {@link TelephonyManager#getSimCarrierId()}
- * while your app is running. You can also use a {@link JobService} to ensure your app
+ * while your app is running. You can also use a {@link android.app.job.JobService}
+ * to ensure your app
* is notified of changes to the {@link Uri} even when it is not running.
- * Note, however, that using a {@link JobService} does not guarantee timely delivery of
- * updates to the {@link Uri}.
+ * Note, however, that using a {@link android.app.job.JobService} does not guarantee
+ * timely delivery of updates to the {@link Uri}.
*
* @param subscriptionId the subscriptionId to receive updates on
* @return the Uri used to observe carrier identity changes
@@ -4399,10 +4403,11 @@
* <p>
* Use this {@link Uri} with a {@link ContentObserver} to be notified of changes to the
* specific carrier identity {@link TelephonyManager#getSimSpecificCarrierId()}
- * while your app is running. You can also use a {@link JobService} to ensure your app
+ * while your app is running. You can also use a {@link android.app.job.JobService}
+ * to ensure your app
* is notified of changes to the {@link Uri} even when it is not running.
- * Note, however, that using a {@link JobService} does not guarantee timely delivery of
- * updates to the {@link Uri}.
+ * Note, however, that using a {@link android.app.job.JobService} does not guarantee timely
+ * delivery of updates to the {@link Uri}.
*
* @param subscriptionId the subscriptionId to receive updates on
* @return the Uri used to observe specific carrier identity changes
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 9849ec7..1dd2635 100755
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -468,6 +468,14 @@
"notify_handover_video_from_wifi_to_lte_bool";
/**
+ * Flag specifying whether the carrier supports merging a RTT call with a voice call,
+ * downgrading the call in the process.
+ * @hide
+ */
+ public static final String KEY_ALLOW_MERGING_RTT_CALLS_BOOL =
+ "allow_merging_rtt_calls_bool";
+
+ /**
* Flag specifying whether the carrier wants to notify the user when a VT call has been handed
* over from LTE to WIFI.
* <p>
@@ -2667,6 +2675,22 @@
"5g_icon_configuration_string";
/**
+ * Timeout in second for displaying 5G icon, default value is 0 which means the timer is
+ * disabled.
+ *
+ * System UI will show the 5G icon and start a timer with the timeout from this config when the
+ * device connects to a 5G cell. System UI stops displaying 5G icon when both the device
+ * disconnects from 5G cell and the timer is expired.
+ *
+ * If 5G is reacquired during this timer, the timer is canceled and restarted when 5G is next
+ * lost. Allows us to momentarily lose 5G without blinking the icon.
+ *
+ * @hide
+ */
+ public static final String KEY_5G_ICON_DISPLAY_GRACE_PERIOD_SEC_INT =
+ "5g_icon_display_grace_period_sec_int";
+
+ /**
* Support ASCII 7-BIT encoding for long SMS. This carrier config is used to enable
* this feature.
* @hide
@@ -3121,6 +3145,7 @@
sDefaults.putBoolean(KEY_CARRIER_VOLTE_AVAILABLE_BOOL, false);
sDefaults.putBoolean(KEY_CARRIER_VT_AVAILABLE_BOOL, false);
sDefaults.putBoolean(KEY_NOTIFY_HANDOVER_VIDEO_FROM_WIFI_TO_LTE_BOOL, false);
+ sDefaults.putBoolean(KEY_ALLOW_MERGING_RTT_CALLS_BOOL, false);
sDefaults.putBoolean(KEY_NOTIFY_HANDOVER_VIDEO_FROM_LTE_TO_WIFI_BOOL, false);
sDefaults.putBoolean(KEY_SUPPORT_DOWNGRADE_VT_TO_AUDIO_BOOL, true);
sDefaults.putString(KEY_DEFAULT_VM_NUMBER_STRING, "");
@@ -3477,6 +3502,7 @@
sDefaults.putInt(KEY_CALL_WAITING_SERVICE_CLASS_INT, 1 /* SERVICE_CLASS_VOICE */);
sDefaults.putString(KEY_5G_ICON_CONFIGURATION_STRING,
"connected_mmwave:None,connected:5G,not_restricted:None,restricted:None");
+ sDefaults.putInt(KEY_5G_ICON_DISPLAY_GRACE_PERIOD_SEC_INT, 0);
sDefaults.putBoolean(KEY_ASCII_7_BIT_SUPPORT_FOR_LONG_MESSAGE_BOOL, false);
/* Default value is minimum RSRP level needed for SIGNAL_STRENGTH_GOOD */
sDefaults.putInt(KEY_OPPORTUNISTIC_NETWORK_ENTRY_THRESHOLD_RSRP_INT, -108);
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index 2822fcc..8c53c51 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -34,7 +34,6 @@
import android.annotation.UnsupportedAppUsage;
import android.app.BroadcastOptions;
import android.app.PendingIntent;
-import android.app.job.JobService;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfo;
@@ -147,10 +146,11 @@
* <p>
* Use this {@link Uri} with a {@link ContentObserver} to be notified of changes to the
* subscription wfc enabled {@link ImsMmTelManager#isVoWiFiSettingEnabled()}
- * while your app is running. You can also use a {@link JobService} to ensure your app
+ * while your app is running. You can also use a {@link android.app.job.JobService}
+ * to ensure your app
* is notified of changes to the {@link Uri} even when it is not running.
- * Note, however, that using a {@link JobService} does not guarantee timely delivery of
- * updates to the {@link Uri}.
+ * Note, however, that using a {@link android.app.job.JobService} does not guarantee timely
+ * delivery of updates to the {@link Uri}.
* To be notified of changes to a specific subId, append subId to the URI
* {@link Uri#withAppendedPath(Uri, String)}.
* @hide
@@ -166,10 +166,10 @@
* Use this {@link Uri} with a {@link ContentObserver} to be notified of changes to the
* subscription advanced calling enabled
* {@link ImsMmTelManager#isAdvancedCallingSettingEnabled()} while your app is running.
- * You can also use a {@link JobService} to ensure your app is notified of changes to the
- * {@link Uri} even when it is not running.
- * Note, however, that using a {@link JobService} does not guarantee timely delivery of
- * updates to the {@link Uri}.
+ * You can also use a {@link android.app.job.JobService} to ensure your app is notified of
+ * changes to the {@link Uri} even when it is not running.
+ * Note, however, that using a {@link android.app.job.JobService} does not guarantee timely
+ * delivery of updates to the {@link Uri}.
* To be notified of changes to a specific subId, append subId to the URI
* {@link Uri#withAppendedPath(Uri, String)}.
* @hide
@@ -184,10 +184,10 @@
* <p>
* Use this {@link Uri} with a {@link ContentObserver} to be notified of changes to the
* subscription wfc mode {@link ImsMmTelManager#getVoWiFiModeSetting()}
- * while your app is running. You can also use a {@link JobService} to ensure your app
- * is notified of changes to the {@link Uri} even when it is not running.
- * Note, however, that using a {@link JobService} does not guarantee timely delivery of
- * updates to the {@link Uri}.
+ * while your app is running. You can also use a {@link android.app.job.JobService} to ensure
+ * your app is notified of changes to the {@link Uri} even when it is not running.
+ * Note, however, that using a {@link android.app.job.JobService} does not guarantee timely
+ * delivery of updates to the {@link Uri}.
* To be notified of changes to a specific subId, append subId to the URI
* {@link Uri#withAppendedPath(Uri, String)}.
* @hide
@@ -201,10 +201,10 @@
* <p>
* Use this {@link Uri} with a {@link ContentObserver} to be notified of changes to the
* subscription wfc roaming mode {@link ImsMmTelManager#getVoWiFiRoamingModeSetting()}
- * while your app is running. You can also use a {@link JobService} to ensure your app
- * is notified of changes to the {@link Uri} even when it is not running.
- * Note, however, that using a {@link JobService} does not guarantee timely delivery of
- * updates to the {@link Uri}.
+ * while your app is running. You can also use a {@link android.app.job.JobService}
+ * to ensure your app is notified of changes to the {@link Uri} even when it is not running.
+ * Note, however, that using a {@link android.app.job.JobService} does not guarantee timely
+ * delivery of updates to the {@link Uri}.
* To be notified of changes to a specific subId, append subId to the URI
* {@link Uri#withAppendedPath(Uri, String)}.
* @hide
@@ -220,10 +220,10 @@
* <p>
* Use this {@link Uri} with a {@link ContentObserver} to be notified of changes to the
* subscription vt enabled {@link ImsMmTelManager#isVtSettingEnabled()}
- * while your app is running. You can also use a {@link JobService} to ensure your app
- * is notified of changes to the {@link Uri} even when it is not running.
- * Note, however, that using a {@link JobService} does not guarantee timely delivery of
- * updates to the {@link Uri}.
+ * while your app is running. You can also use a {@link android.app.job.JobService} to ensure
+ * your app is notified of changes to the {@link Uri} even when it is not running.
+ * Note, however, that using a {@link android.app.job.JobService} does not guarantee timely
+ * delivery of updates to the {@link Uri}.
* To be notified of changes to a specific subId, append subId to the URI
* {@link Uri#withAppendedPath(Uri, String)}.
* @hide
@@ -238,10 +238,10 @@
* <p>
* Use this {@link Uri} with a {@link ContentObserver} to be notified of changes to the
* subscription wfc roaming enabled {@link ImsMmTelManager#isVoWiFiRoamingSettingEnabled()}
- * while your app is running. You can also use a {@link JobService} to ensure your app
- * is notified of changes to the {@link Uri} even when it is not running.
- * Note, however, that using a {@link JobService} does not guarantee timely delivery of
- * updates to the {@link Uri}.
+ * while your app is running. You can also use a {@link android.app.job.JobService} to ensure
+ * your app is notified of changes to the {@link Uri} even when it is not running.
+ * Note, however, that using a {@link android.app.job.JobService} does not guarantee timely
+ * delivery of updates to the {@link Uri}.
* To be notified of changes to a specific subId, append subId to the URI
* {@link Uri#withAppendedPath(Uri, String)}.
* @hide
diff --git a/telephony/java/android/telephony/ims/feature/ImsFeature.java b/telephony/java/android/telephony/ims/feature/ImsFeature.java
index 3bec8b0..8f89899 100644
--- a/telephony/java/android/telephony/ims/feature/ImsFeature.java
+++ b/telephony/java/android/telephony/ims/feature/ImsFeature.java
@@ -34,7 +34,9 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Collections;
+import java.util.HashMap;
import java.util.Iterator;
+import java.util.Map;
import java.util.Set;
import java.util.WeakHashMap;
@@ -106,6 +108,16 @@
public static final int FEATURE_MAX = 3;
/**
+ * Used for logging purposes.
+ * @hide
+ */
+ public static final Map<Integer, String> FEATURE_LOG_MAP = new HashMap<Integer, String>() {{
+ put(FEATURE_EMERGENCY_MMTEL, "EMERGENCY_MMTEL");
+ put(FEATURE_MMTEL, "MMTEL");
+ put(FEATURE_RCS, "RCS");
+ }};
+
+ /**
* Integer values defining IMS features that are supported in ImsFeature.
* @hide
*/
@@ -150,6 +162,16 @@
public static final int STATE_READY = 2;
/**
+ * Used for logging purposes.
+ * @hide
+ */
+ public static final Map<Integer, String> STATE_LOG_MAP = new HashMap<Integer, String>() {{
+ put(STATE_UNAVAILABLE, "UNAVAILABLE");
+ put(STATE_INITIALIZING, "INITIALIZING");
+ put(STATE_READY, "READY");
+ }};
+
+ /**
* Integer values defining the result codes that should be returned from
* {@link #changeEnabledCapabilities} when the framework tries to set a feature's capability.
* @hide
diff --git a/telephony/java/android/telephony/ims/stub/ImsFeatureConfiguration.java b/telephony/java/android/telephony/ims/stub/ImsFeatureConfiguration.java
index 6ab9465..3b298bb 100644
--- a/telephony/java/android/telephony/ims/stub/ImsFeatureConfiguration.java
+++ b/telephony/java/android/telephony/ims/stub/ImsFeatureConfiguration.java
@@ -21,7 +21,6 @@
import android.os.Parcelable;
import android.telephony.ims.feature.ImsFeature;
import android.util.ArraySet;
-import android.util.Pair;
import java.util.Set;
@@ -80,7 +79,7 @@
@Override
public String toString() {
- return "{s=" + slotId + ", f=" + featureType + "}";
+ return "{s=" + slotId + ", f=" + ImsFeature.FEATURE_LOG_MAP.get(featureType) + "}";
}
}
diff --git a/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java b/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java
index af993be..e9a177d 100644
--- a/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java
+++ b/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java
@@ -115,7 +115,7 @@
final Context otherContext;
try {
otherContext = context.createPackageContextAsUser(context.getPackageName(),
- /* flags =*/ 0, new UserHandle(currentUser));
+ /* flags =*/ 0, UserHandle.of(currentUser));
return otherContext.getContentResolver();
} catch (NameNotFoundException e) {
Rlog.e(LOG_TAG, "Can't find self package", e);
diff --git a/telephony/java/com/android/internal/telephony/CarrierAppUtils.java b/telephony/java/com/android/internal/telephony/CarrierAppUtils.java
index 6498e49..0d4fd0f 100644
--- a/telephony/java/com/android/internal/telephony/CarrierAppUtils.java
+++ b/telephony/java/com/android/internal/telephony/CarrierAppUtils.java
@@ -21,6 +21,7 @@
import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
+import android.content.res.Resources;
import android.os.RemoteException;
import android.permission.IPermissionManager;
import android.provider.Settings;
@@ -29,7 +30,9 @@
import android.util.ArraySet;
import android.util.Slog;
+import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.ArrayUtils;
import com.android.server.SystemConfig;
import java.util.ArrayList;
@@ -143,9 +146,12 @@
try {
for (ApplicationInfo ai : candidates) {
String packageName = ai.packageName;
- boolean hasPrivileges = telephonyManager != null &&
- telephonyManager.checkCarrierPrivilegesForPackageAnyPhone(packageName) ==
- TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS;
+ String[] restrictedCarrierApps = Resources.getSystem().getStringArray(
+ R.array.config_restrictedPreinstalledCarrierApps);
+ boolean hasPrivileges = telephonyManager != null
+ && telephonyManager.checkCarrierPrivilegesForPackageAnyPhone(packageName)
+ == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS
+ && !ArrayUtils.contains(restrictedCarrierApps, packageName);
// add hiddenUntilInstalled flag for carrier apps and associated apps
packageManager.setSystemAppHiddenUntilInstalled(packageName, true);
diff --git a/telephony/java/com/android/internal/telephony/SmsApplication.java b/telephony/java/com/android/internal/telephony/SmsApplication.java
index 90e2c1f..62d3536 100644
--- a/telephony/java/com/android/internal/telephony/SmsApplication.java
+++ b/telephony/java/com/android/internal/telephony/SmsApplication.java
@@ -806,7 +806,7 @@
if (userId != UserHandle.USER_SYSTEM) {
try {
userContext = mContext.createPackageContextAsUser(mContext.getPackageName(), 0,
- new UserHandle(userId));
+ UserHandle.of(userId));
} catch (NameNotFoundException nnfe) {
if (DEBUG_MULTIUSER) {
Log.w(LOG_TAG, "Unable to create package context for user " + userId);
diff --git a/test-mock/Android.bp b/test-mock/Android.bp
index a5cd175..0129c4c 100644
--- a/test-mock/Android.bp
+++ b/test-mock/Android.bp
@@ -25,7 +25,7 @@
"android.test.mock",
],
- srcs_lib: "framework",
+ srcs_lib: "framework-minus-apex",
srcs_lib_whitelist_dirs: ["core/java"],
srcs_lib_whitelist_pkgs: ["android"],
compile_dex: true,
diff --git a/tests/Codegen/src/com/android/codegentest/SampleDataClass.java b/tests/Codegen/src/com/android/codegentest/SampleDataClass.java
index b30fde4..30bb3ef 100644
--- a/tests/Codegen/src/com/android/codegentest/SampleDataClass.java
+++ b/tests/Codegen/src/com/android/codegentest/SampleDataClass.java
@@ -1798,7 +1798,7 @@
}
@DataClass.Generated(
- time = 1565048798524L,
+ time = 1565126122525L,
codegenVersion = "1.0.0",
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)")
diff --git a/tests/Codegen/src/com/android/codegentest/SampleWithCustomBuilder.java b/tests/Codegen/src/com/android/codegentest/SampleWithCustomBuilder.java
index d88035c..11f03a7 100644
--- a/tests/Codegen/src/com/android/codegentest/SampleWithCustomBuilder.java
+++ b/tests/Codegen/src/com/android/codegentest/SampleWithCustomBuilder.java
@@ -176,7 +176,7 @@
}
@DataClass.Generated(
- time = 1565048799396L,
+ time = 1565126123496L,
codegenVersion = "1.0.0",
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\nclass SampleWithCustomBuilder extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genBuilder=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 []")
diff --git a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java
index a27df47..2c0432a 100644
--- a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java
+++ b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java
@@ -154,15 +154,8 @@
// TODO: Race condition between the timeout and when the broadcast is
// received could lead to test flakiness.
Intent broadcast = broadcastReceiver.poll(5, TimeUnit.SECONDS);
- if (context.getUser().isSystem()) {
- // Only system user should receive those broadcasts.
- assertThat(broadcast).isNotNull();
- assertThat(broadcastReceiver.poll(0, TimeUnit.SECONDS)).isNull();
- } else {
- // This is in case the test was running under a secondary user, in which case
- // the broadcast won't be received here.
- assertThat(broadcast).isNull();
- }
+ assertThat(broadcast).isNotNull();
+ assertThat(broadcastReceiver.poll(0, TimeUnit.SECONDS)).isNull();
// Verify the recent rollback has been recorded.
RollbackInfo committed = getUniqueRollbackInfoForPackage(
diff --git a/tests/net/Android.bp b/tests/net/Android.bp
index 5260b30..502aa97 100644
--- a/tests/net/Android.bp
+++ b/tests/net/Android.bp
@@ -56,6 +56,7 @@
"androidx.test.rules",
"FrameworksNetCommonTests",
"frameworks-base-testutils",
+ "frameworks-net-integration-testutils",
"framework-protos",
"mockito-target-minus-junit4",
"net-tests-utils",
diff --git a/tests/net/integration/Android.bp b/tests/net/integration/Android.bp
new file mode 100644
index 0000000..16a68d7
--- /dev/null
+++ b/tests/net/integration/Android.bp
@@ -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.
+//
+
+// Utilities for testing framework code both in integration and unit tests.
+java_library {
+ name: "frameworks-net-integration-testutils",
+ srcs: ["util/**/*.java", "util/**/*.kt"],
+ static_libs: [
+ "androidx.annotation_annotation",
+ "androidx.test.rules",
+ "junit",
+ "net-tests-utils",
+ ],
+ libs: [
+ "services.core",
+ "services.net",
+ ],
+}
diff --git a/tests/net/integration/util/com/android/server/ConnectivityServiceTestUtils.kt b/tests/net/integration/util/com/android/server/ConnectivityServiceTestUtils.kt
new file mode 100644
index 0000000..fa2b99c
--- /dev/null
+++ b/tests/net/integration/util/com/android/server/ConnectivityServiceTestUtils.kt
@@ -0,0 +1,41 @@
+/*
+ * 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
+
+import android.net.ConnectivityManager.TYPE_BLUETOOTH
+import android.net.ConnectivityManager.TYPE_ETHERNET
+import android.net.ConnectivityManager.TYPE_MOBILE
+import android.net.ConnectivityManager.TYPE_NONE
+import android.net.ConnectivityManager.TYPE_TEST
+import android.net.ConnectivityManager.TYPE_VPN
+import android.net.ConnectivityManager.TYPE_WIFI
+import android.net.NetworkCapabilities.TRANSPORT_BLUETOOTH
+import android.net.NetworkCapabilities.TRANSPORT_CELLULAR
+import android.net.NetworkCapabilities.TRANSPORT_ETHERNET
+import android.net.NetworkCapabilities.TRANSPORT_TEST
+import android.net.NetworkCapabilities.TRANSPORT_VPN
+import android.net.NetworkCapabilities.TRANSPORT_WIFI
+
+fun transportToLegacyType(transport: Int) = when (transport) {
+ TRANSPORT_BLUETOOTH -> TYPE_BLUETOOTH
+ TRANSPORT_CELLULAR -> TYPE_MOBILE
+ TRANSPORT_ETHERNET -> TYPE_ETHERNET
+ TRANSPORT_TEST -> TYPE_TEST
+ TRANSPORT_VPN -> TYPE_VPN
+ TRANSPORT_WIFI -> TYPE_WIFI
+ else -> TYPE_NONE
+}
\ No newline at end of file
diff --git a/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java b/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java
new file mode 100644
index 0000000..1e8d83c
--- /dev/null
+++ b/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java
@@ -0,0 +1,267 @@
+/*
+ * 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;
+
+import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN;
+import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
+import static android.net.NetworkCapabilities.TRANSPORT_ETHERNET;
+import static android.net.NetworkCapabilities.TRANSPORT_VPN;
+import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
+import static android.net.NetworkCapabilities.TRANSPORT_WIFI_AWARE;
+
+import static com.android.server.ConnectivityServiceTestUtilsKt.transportToLegacyType;
+
+import static junit.framework.Assert.assertTrue;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+
+import android.content.Context;
+import android.net.ConnectivityManager;
+import android.net.LinkProperties;
+import android.net.Network;
+import android.net.NetworkAgent;
+import android.net.NetworkCapabilities;
+import android.net.NetworkFactory;
+import android.net.NetworkInfo;
+import android.net.NetworkMisc;
+import android.net.NetworkSpecifier;
+import android.net.SocketKeepalive;
+import android.net.UidRange;
+import android.os.ConditionVariable;
+import android.os.HandlerThread;
+import android.os.Message;
+import android.util.Log;
+
+import com.android.server.connectivity.ConnectivityConstants;
+import com.android.testutils.HandlerUtilsKt;
+import com.android.testutils.TestableNetworkCallback;
+
+import java.util.Set;
+
+public class NetworkAgentWrapper implements TestableNetworkCallback.HasNetwork {
+ private final NetworkInfo mNetworkInfo;
+ private final NetworkCapabilities mNetworkCapabilities;
+ private final HandlerThread mHandlerThread;
+ private final Context mContext;
+ private final String mLogTag;
+
+ private final ConditionVariable mDisconnected = new ConditionVariable();
+ private final ConditionVariable mPreventReconnectReceived = new ConditionVariable();
+ private int mScore;
+ private NetworkAgent mNetworkAgent;
+ private int mStartKeepaliveError = SocketKeepalive.ERROR_UNSUPPORTED;
+ private int mStopKeepaliveError = SocketKeepalive.NO_KEEPALIVE;
+ private Integer mExpectedKeepaliveSlot = null;
+
+ public NetworkAgentWrapper(int transport, LinkProperties linkProperties, Context context)
+ throws Exception {
+ final int type = transportToLegacyType(transport);
+ final String typeName = ConnectivityManager.getNetworkTypeName(type);
+ mNetworkInfo = new NetworkInfo(type, 0, typeName, "Mock");
+ mNetworkCapabilities = new NetworkCapabilities();
+ mNetworkCapabilities.addTransportType(transport);
+ switch (transport) {
+ case TRANSPORT_ETHERNET:
+ mScore = 70;
+ break;
+ case TRANSPORT_WIFI:
+ mScore = 60;
+ break;
+ case TRANSPORT_CELLULAR:
+ mScore = 50;
+ break;
+ case TRANSPORT_WIFI_AWARE:
+ mScore = 20;
+ break;
+ case TRANSPORT_VPN:
+ mNetworkCapabilities.removeCapability(NET_CAPABILITY_NOT_VPN);
+ mScore = ConnectivityConstants.VPN_DEFAULT_SCORE;
+ break;
+ default:
+ throw new UnsupportedOperationException("unimplemented network type");
+ }
+ mContext = context;
+ mLogTag = "Mock-" + typeName;
+ mHandlerThread = new HandlerThread(mLogTag);
+ mHandlerThread.start();
+
+ mNetworkAgent = makeNetworkAgent(linkProperties);
+ }
+
+ protected InstrumentedNetworkAgent makeNetworkAgent(LinkProperties linkProperties)
+ throws Exception {
+ return new InstrumentedNetworkAgent(this, linkProperties);
+ }
+
+ public static class InstrumentedNetworkAgent extends NetworkAgent {
+ private final NetworkAgentWrapper mWrapper;
+
+ public InstrumentedNetworkAgent(NetworkAgentWrapper wrapper, LinkProperties lp) {
+ super(wrapper.mHandlerThread.getLooper(), wrapper.mContext, wrapper.mLogTag,
+ wrapper.mNetworkInfo, wrapper.mNetworkCapabilities, lp, wrapper.mScore,
+ new NetworkMisc(), NetworkFactory.SerialNumber.NONE);
+ mWrapper = wrapper;
+ }
+
+ @Override
+ public void unwanted() {
+ mWrapper.mDisconnected.open();
+ }
+
+ @Override
+ public void startSocketKeepalive(Message msg) {
+ int slot = msg.arg1;
+ if (mWrapper.mExpectedKeepaliveSlot != null) {
+ assertEquals((int) mWrapper.mExpectedKeepaliveSlot, slot);
+ }
+ onSocketKeepaliveEvent(slot, mWrapper.mStartKeepaliveError);
+ }
+
+ @Override
+ public void stopSocketKeepalive(Message msg) {
+ onSocketKeepaliveEvent(msg.arg1, mWrapper.mStopKeepaliveError);
+ }
+
+ @Override
+ protected void preventAutomaticReconnect() {
+ mWrapper.mPreventReconnectReceived.open();
+ }
+
+ @Override
+ protected void addKeepalivePacketFilter(Message msg) {
+ Log.i(mWrapper.mLogTag, "Add keepalive packet filter.");
+ }
+
+ @Override
+ protected void removeKeepalivePacketFilter(Message msg) {
+ Log.i(mWrapper.mLogTag, "Remove keepalive packet filter.");
+ }
+ }
+
+ public void adjustScore(int change) {
+ mScore += change;
+ mNetworkAgent.sendNetworkScore(mScore);
+ }
+
+ public int getScore() {
+ return mScore;
+ }
+
+ public void explicitlySelected(boolean explicitlySelected, boolean acceptUnvalidated) {
+ mNetworkAgent.explicitlySelected(explicitlySelected, acceptUnvalidated);
+ }
+
+ public void addCapability(int capability) {
+ mNetworkCapabilities.addCapability(capability);
+ mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
+ }
+
+ public void removeCapability(int capability) {
+ mNetworkCapabilities.removeCapability(capability);
+ mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
+ }
+
+ public void setUids(Set<UidRange> uids) {
+ mNetworkCapabilities.setUids(uids);
+ mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
+ }
+
+ public void setSignalStrength(int signalStrength) {
+ mNetworkCapabilities.setSignalStrength(signalStrength);
+ mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
+ }
+
+ public void setNetworkSpecifier(NetworkSpecifier networkSpecifier) {
+ mNetworkCapabilities.setNetworkSpecifier(networkSpecifier);
+ mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
+ }
+
+ public void setNetworkCapabilities(NetworkCapabilities nc, boolean sendToConnectivityService) {
+ mNetworkCapabilities.set(nc);
+ if (sendToConnectivityService) {
+ mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
+ }
+ }
+
+ public void connect() {
+ assertNotEquals("MockNetworkAgents can only be connected once",
+ getNetworkInfo().getDetailedState(), NetworkInfo.DetailedState.CONNECTED);
+ mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED, null, null);
+ mNetworkAgent.sendNetworkInfo(mNetworkInfo);
+ }
+
+ public void suspend() {
+ mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.SUSPENDED, null, null);
+ mNetworkAgent.sendNetworkInfo(mNetworkInfo);
+ }
+
+ public void resume() {
+ mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED, null, null);
+ mNetworkAgent.sendNetworkInfo(mNetworkInfo);
+ }
+
+ public void disconnect() {
+ mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.DISCONNECTED, null, null);
+ mNetworkAgent.sendNetworkInfo(mNetworkInfo);
+ }
+
+ @Override
+ public Network getNetwork() {
+ return new Network(mNetworkAgent.netId);
+ }
+
+ public void expectPreventReconnectReceived(long timeoutMs) {
+ assertTrue(mPreventReconnectReceived.block(timeoutMs));
+ }
+
+ public void expectDisconnected(long timeoutMs) {
+ assertTrue(mDisconnected.block(timeoutMs));
+ }
+
+ public void sendLinkProperties(LinkProperties lp) {
+ mNetworkAgent.sendLinkProperties(lp);
+ }
+
+ public void setStartKeepaliveEvent(int reason) {
+ mStartKeepaliveError = reason;
+ }
+
+ public void setStopKeepaliveEvent(int reason) {
+ mStopKeepaliveError = reason;
+ }
+
+ public void setExpectedKeepaliveSlot(Integer slot) {
+ mExpectedKeepaliveSlot = slot;
+ }
+
+ public NetworkAgent getNetworkAgent() {
+ return mNetworkAgent;
+ }
+
+ public NetworkInfo getNetworkInfo() {
+ return mNetworkInfo;
+ }
+
+ public NetworkCapabilities getNetworkCapabilities() {
+ return mNetworkCapabilities;
+ }
+
+ public void waitForIdle(long timeoutMs) {
+ HandlerUtilsKt.waitForIdle(mHandlerThread, timeoutMs);
+ }
+}
diff --git a/tests/net/integration/util/com/android/server/TestNetIdManager.kt b/tests/net/integration/util/com/android/server/TestNetIdManager.kt
new file mode 100644
index 0000000..eb290dc
--- /dev/null
+++ b/tests/net/integration/util/com/android/server/TestNetIdManager.kt
@@ -0,0 +1,38 @@
+/*
+ * 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
+
+import java.util.concurrent.atomic.AtomicInteger
+
+/**
+ * A [NetIdManager] that generates ID starting from [NetIdManager.MAX_NET_ID] and decreasing, rather
+ * than starting from [NetIdManager.MIN_NET_ID] and increasing.
+ *
+ * Useful for testing ConnectivityService, to minimize the risk of test ConnectivityService netIDs
+ * overlapping with netIDs used by the real ConnectivityService on the device.
+ *
+ * IDs may still overlap if many networks have been used on the device (so the "real" netIDs
+ * are close to MAX_NET_ID), but this is typically not the case when running unit tests. Also, there
+ * is no way to fully solve the overlap issue without altering ID allocation in non-test code, as
+ * the real ConnectivityService could start using netIds that have been used by the test in the
+ * past.
+ */
+class TestNetIdManager : NetIdManager() {
+ private val nextId = AtomicInteger(MAX_NET_ID)
+ override fun reserveNetId() = nextId.decrementAndGet()
+ override fun releaseNetId(id: Int) = Unit
+}
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index 5cc95d9..f3c735c 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -28,8 +28,6 @@
import static android.net.ConnectivityManager.TYPE_MOBILE;
import static android.net.ConnectivityManager.TYPE_MOBILE_FOTA;
import static android.net.ConnectivityManager.TYPE_MOBILE_MMS;
-import static android.net.ConnectivityManager.TYPE_NONE;
-import static android.net.ConnectivityManager.TYPE_VPN;
import static android.net.ConnectivityManager.TYPE_WIFI;
import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_DNS;
import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_FALLBACK;
@@ -69,6 +67,7 @@
import static android.net.NetworkPolicyManager.RULE_REJECT_METERED;
import static android.net.RouteInfo.RTN_UNREACHABLE;
+import static com.android.server.ConnectivityServiceTestUtilsKt.transportToLegacyType;
import static com.android.testutils.ConcurrentUtilsKt.await;
import static com.android.testutils.ConcurrentUtilsKt.durationOf;
import static com.android.testutils.ExceptionUtils.ignoreExceptions;
@@ -86,6 +85,7 @@
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Matchers.anyInt;
@@ -93,6 +93,7 @@
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
@@ -105,6 +106,7 @@
import static org.mockito.Mockito.when;
import android.annotation.NonNull;
+import android.app.AlarmManager;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
@@ -125,6 +127,7 @@
import android.net.ConnectivityManager.TooManyRequestsException;
import android.net.ConnectivityThread;
import android.net.IDnsResolver;
+import android.net.IIpConnectivityMetrics;
import android.net.INetd;
import android.net.INetworkMonitor;
import android.net.INetworkMonitorCallbacks;
@@ -139,12 +142,8 @@
import android.net.LinkProperties;
import android.net.MatchAllNetworkSpecifier;
import android.net.Network;
-import android.net.NetworkAgent;
import android.net.NetworkCapabilities;
import android.net.NetworkFactory;
-import android.net.NetworkInfo;
-import android.net.NetworkInfo.DetailedState;
-import android.net.NetworkMisc;
import android.net.NetworkRequest;
import android.net.NetworkSpecifier;
import android.net.NetworkStack;
@@ -168,7 +167,6 @@
import android.os.HandlerThread;
import android.os.INetworkManagementService;
import android.os.Looper;
-import android.os.Message;
import android.os.Parcel;
import android.os.ParcelFileDescriptor;
import android.os.Parcelable;
@@ -265,10 +263,12 @@
// timeout. For this, our assertions should run fast enough to leave less than
// (mService.mLingerDelayMs - TEST_CALLBACK_TIMEOUT_MS) between the time callbacks are
// supposedly fired, and the time we call expectCallback.
- private final static int TEST_CALLBACK_TIMEOUT_MS = 200;
+ private static final int TEST_CALLBACK_TIMEOUT_MS = 200;
// Chosen to be less than TEST_CALLBACK_TIMEOUT_MS. This ensures that requests have time to
// complete before callbacks are verified.
- private final static int TEST_REQUEST_TIMEOUT_MS = 150;
+ private static final int TEST_REQUEST_TIMEOUT_MS = 150;
+
+ private static final int UNREASONABLY_LONG_ALARM_WAIT_MS = 1000;
private static final String CLAT_PREFIX = "v4-";
private static final String MOBILE_IFNAME = "test_rmnet_data0";
@@ -276,15 +276,19 @@
private static final String[] EMPTY_STRING_ARRAY = new String[0];
private MockContext mServiceContext;
- private WrappedConnectivityService mService;
+ private HandlerThread mCsHandlerThread;
+ private ConnectivityService mService;
private WrappedConnectivityManager mCm;
- private MockNetworkAgent mWiFiNetworkAgent;
- private MockNetworkAgent mCellNetworkAgent;
- private MockNetworkAgent mEthernetNetworkAgent;
+ private TestNetworkAgentWrapper mWiFiNetworkAgent;
+ private TestNetworkAgentWrapper mCellNetworkAgent;
+ private TestNetworkAgentWrapper mEthernetNetworkAgent;
private MockVpn mMockVpn;
private Context mContext;
private INetworkPolicyListener mPolicyListener;
+ private WrappedMultinetworkPolicyTracker mPolicyTracker;
+ private HandlerThread mAlarmManagerThread;
+ @Mock IIpConnectivityMetrics mIpConnectivityMetrics;
@Mock IpConnectivityMetrics.Logger mMetricsService;
@Mock DefaultNetworkMetrics mDefaultNetworkMetrics;
@Mock INetworkManagementService mNetworkManagementService;
@@ -296,6 +300,7 @@
@Mock PackageManager mPackageManager;
@Mock UserManager mUserManager;
@Mock NotificationManager mNotificationManager;
+ @Mock AlarmManager mAlarmManager;
private ArgumentCaptor<ResolverParamsParcel> mResolverParamsParcelCaptor =
ArgumentCaptor.forClass(ResolverParamsParcel.class);
@@ -368,6 +373,7 @@
if (Context.NOTIFICATION_SERVICE.equals(name)) return mNotificationManager;
if (Context.NETWORK_STACK_SERVICE.equals(name)) return mNetworkStack;
if (Context.USER_SERVICE.equals(name)) return mUserManager;
+ if (Context.ALARM_SERVICE.equals(name)) return mAlarmManager;
return super.getSystemService(name);
}
@@ -397,25 +403,20 @@
}
}
- public void waitForIdle(int timeoutMsAsInt) {
- long timeoutMs = timeoutMsAsInt;
- HandlerUtilsKt.waitForIdle(mService.mHandlerThread, timeoutMs);
- waitForIdle(mCellNetworkAgent, timeoutMs);
- waitForIdle(mWiFiNetworkAgent, timeoutMs);
- waitForIdle(mEthernetNetworkAgent, timeoutMs);
- HandlerUtilsKt.waitForIdle(mService.mHandlerThread, timeoutMs);
- HandlerUtilsKt.waitForIdle(ConnectivityThread.get(), timeoutMs);
+ private void waitForIdle() {
+ HandlerUtilsKt.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
+ waitForIdle(mCellNetworkAgent, TIMEOUT_MS);
+ waitForIdle(mWiFiNetworkAgent, TIMEOUT_MS);
+ waitForIdle(mEthernetNetworkAgent, TIMEOUT_MS);
+ HandlerUtilsKt.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
+ HandlerUtilsKt.waitForIdle(ConnectivityThread.get(), TIMEOUT_MS);
}
- public void waitForIdle(MockNetworkAgent agent, long timeoutMs) {
+ private void waitForIdle(TestNetworkAgentWrapper agent, long timeoutMs) {
if (agent == null) {
return;
}
- HandlerUtilsKt.waitForIdle(agent.mHandlerThread, timeoutMs);
- }
-
- private void waitForIdle() {
- waitForIdle(TIMEOUT_MS);
+ agent.waitForIdle(timeoutMs);
}
@Test
@@ -429,7 +430,7 @@
// Bring up a network that we can use to send messages to ConnectivityService.
ConditionVariable cv = waitForConnectivityBroadcasts(1);
- mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+ mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
mWiFiNetworkAgent.connect(false);
waitFor(cv);
Network n = mWiFiNetworkAgent.getNetwork();
@@ -449,7 +450,7 @@
public void verifyThatNotWaitingForIdleCausesRaceConditions() throws Exception {
// Bring up a network that we can use to send messages to ConnectivityService.
ConditionVariable cv = waitForConnectivityBroadcasts(1);
- mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+ mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
mWiFiNetworkAgent.connect(false);
waitFor(cv);
Network n = mWiFiNetworkAgent.getNetwork();
@@ -469,7 +470,7 @@
fail("expected race condition at least once in " + attempts + " attempts");
}
- private class MockNetworkAgent implements TestableNetworkCallback.HasNetwork {
+ private class TestNetworkAgentWrapper extends NetworkAgentWrapper {
private static final int VALIDATION_RESULT_BASE = NETWORK_VALIDATION_PROBE_DNS
| NETWORK_VALIDATION_PROBE_HTTP
| NETWORK_VALIDATION_PROBE_HTTPS;
@@ -480,86 +481,35 @@
| NETWORK_VALIDATION_RESULT_PARTIAL;
private static final int VALIDATION_RESULT_INVALID = 0;
- private final INetworkMonitor mNetworkMonitor;
- private final NetworkInfo mNetworkInfo;
- private final NetworkCapabilities mNetworkCapabilities;
- private final HandlerThread mHandlerThread;
- private final ConditionVariable mDisconnected = new ConditionVariable();
- private final ConditionVariable mNetworkStatusReceived = new ConditionVariable();
- private final ConditionVariable mPreventReconnectReceived = new ConditionVariable();
- private int mScore;
- private NetworkAgent mNetworkAgent;
- private int mStartKeepaliveError = SocketKeepalive.ERROR_UNSUPPORTED;
- private int mStopKeepaliveError = SocketKeepalive.NO_KEEPALIVE;
- private Integer mExpectedKeepaliveSlot = null;
- // Contains the redirectUrl from networkStatus(). Before reading, wait for
- // mNetworkStatusReceived.
- private String mRedirectUrl;
-
+ private INetworkMonitor mNetworkMonitor;
private INetworkMonitorCallbacks mNmCallbacks;
private int mNmValidationResult = VALIDATION_RESULT_BASE;
private String mNmValidationRedirectUrl = null;
private boolean mNmProvNotificationRequested = false;
- void setNetworkValid() {
- mNmValidationResult = VALIDATION_RESULT_VALID;
- mNmValidationRedirectUrl = null;
- }
+ private final ConditionVariable mNetworkStatusReceived = new ConditionVariable();
+ // Contains the redirectUrl from networkStatus(). Before reading, wait for
+ // mNetworkStatusReceived.
+ private String mRedirectUrl;
- void setNetworkInvalid() {
- mNmValidationResult = VALIDATION_RESULT_INVALID;
- mNmValidationRedirectUrl = null;
- }
-
- void setNetworkPortal(String redirectUrl) {
- setNetworkInvalid();
- mNmValidationRedirectUrl = redirectUrl;
- }
-
- void setNetworkPartial() {
- mNmValidationResult = VALIDATION_RESULT_PARTIAL;
- mNmValidationRedirectUrl = null;
- }
-
- void setNetworkPartialValid() {
- mNmValidationResult = VALIDATION_RESULT_PARTIAL | VALIDATION_RESULT_VALID;
- mNmValidationRedirectUrl = null;
- }
-
- MockNetworkAgent(int transport) throws Exception {
+ TestNetworkAgentWrapper(int transport) throws Exception {
this(transport, new LinkProperties());
}
- MockNetworkAgent(int transport, LinkProperties linkProperties) throws Exception {
- final int type = transportToLegacyType(transport);
- final String typeName = ConnectivityManager.getNetworkTypeName(type);
- mNetworkInfo = new NetworkInfo(type, 0, typeName, "Mock");
- mNetworkCapabilities = new NetworkCapabilities();
- mNetworkCapabilities.addTransportType(transport);
- switch (transport) {
- case TRANSPORT_ETHERNET:
- mScore = 70;
- break;
- case TRANSPORT_WIFI:
- mScore = 60;
- break;
- case TRANSPORT_CELLULAR:
- mScore = 50;
- break;
- case TRANSPORT_WIFI_AWARE:
- mScore = 20;
- break;
- case TRANSPORT_VPN:
- mNetworkCapabilities.removeCapability(NET_CAPABILITY_NOT_VPN);
- mScore = ConnectivityConstants.VPN_DEFAULT_SCORE;
- break;
- default:
- throw new UnsupportedOperationException("unimplemented network type");
- }
- mHandlerThread = new HandlerThread("Mock-" + typeName);
- mHandlerThread.start();
+ TestNetworkAgentWrapper(int transport, LinkProperties linkProperties)
+ throws Exception {
+ super(transport, linkProperties, mServiceContext);
+ // Waits for the NetworkAgent to be registered, which includes the creation of the
+ // NetworkMonitor.
+ waitForIdle(TIMEOUT_MS);
+ }
+
+ @Override
+ protected InstrumentedNetworkAgent makeNetworkAgent(LinkProperties linkProperties)
+ throws Exception {
mNetworkMonitor = mock(INetworkMonitor.class);
+
final Answer validateAnswer = inv -> {
new Thread(ignoreExceptions(this::onValidationRequested)).start();
return null;
@@ -576,56 +526,20 @@
any() /* name */,
nmCbCaptor.capture());
- mNetworkAgent = new NetworkAgent(mHandlerThread.getLooper(), mServiceContext,
- "Mock-" + typeName, mNetworkInfo, mNetworkCapabilities,
- linkProperties, mScore, new NetworkMisc(), NetworkFactory.SerialNumber.NONE) {
- @Override
- public void unwanted() { mDisconnected.open(); }
-
- @Override
- public void startSocketKeepalive(Message msg) {
- int slot = msg.arg1;
- if (mExpectedKeepaliveSlot != null) {
- assertEquals((int) mExpectedKeepaliveSlot, slot);
- }
- onSocketKeepaliveEvent(slot, mStartKeepaliveError);
- }
-
- @Override
- public void stopSocketKeepalive(Message msg) {
- onSocketKeepaliveEvent(msg.arg1, mStopKeepaliveError);
- }
-
+ final InstrumentedNetworkAgent na = new InstrumentedNetworkAgent(this, linkProperties) {
@Override
public void networkStatus(int status, String redirectUrl) {
mRedirectUrl = redirectUrl;
mNetworkStatusReceived.open();
}
-
- @Override
- protected void preventAutomaticReconnect() {
- mPreventReconnectReceived.open();
- }
-
- @Override
- protected void addKeepalivePacketFilter(Message msg) {
- Log.i(TAG, "Add keepalive packet filter.");
- }
-
- @Override
- protected void removeKeepalivePacketFilter(Message msg) {
- Log.i(TAG, "Remove keepalive packet filter.");
- }
};
- assertEquals(mNetworkAgent.netId, nmNetworkCaptor.getValue().netId);
+ assertEquals(na.netId, nmNetworkCaptor.getValue().netId);
mNmCallbacks = nmCbCaptor.getValue();
mNmCallbacks.onNetworkMonitorCreated(mNetworkMonitor);
- // Waits for the NetworkAgent to be registered, which includes the creation of the
- // NetworkMonitor.
- waitForIdle();
+ return na;
}
private void onValidationRequested() throws Exception {
@@ -645,55 +559,11 @@
}
}
- public void adjustScore(int change) {
- mScore += change;
- mNetworkAgent.sendNetworkScore(mScore);
- }
-
- public int getScore() {
- return mScore;
- }
-
- public void explicitlySelected(boolean explicitlySelected, boolean acceptUnvalidated) {
- mNetworkAgent.explicitlySelected(explicitlySelected, acceptUnvalidated);
- }
-
- public void addCapability(int capability) {
- mNetworkCapabilities.addCapability(capability);
- mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
- }
-
- public void removeCapability(int capability) {
- mNetworkCapabilities.removeCapability(capability);
- mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
- }
-
- public void setUids(Set<UidRange> uids) {
- mNetworkCapabilities.setUids(uids);
- mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
- }
-
- public void setSignalStrength(int signalStrength) {
- mNetworkCapabilities.setSignalStrength(signalStrength);
- mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
- }
-
- public void setNetworkSpecifier(NetworkSpecifier networkSpecifier) {
- mNetworkCapabilities.setNetworkSpecifier(networkSpecifier);
- mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
- }
-
- public void setNetworkCapabilities(NetworkCapabilities nc,
- boolean sendToConnectivityService) {
- mNetworkCapabilities.set(nc);
- if (sendToConnectivityService) {
- mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
- }
- }
-
+ /**
+ * Connect without adding any internet capability.
+ */
public void connectWithoutInternet() {
- mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, null);
- mNetworkAgent.sendNetworkInfo(mNetworkInfo);
+ super.connect();
}
/**
@@ -710,23 +580,21 @@
* @param hasInternet Indicate if network should pretend to have NET_CAPABILITY_INTERNET.
*/
public void connect(boolean validated, boolean hasInternet) {
- assertEquals("MockNetworkAgents can only be connected once",
- mNetworkInfo.getDetailedState(), DetailedState.IDLE);
- assertFalse(mNetworkCapabilities.hasCapability(NET_CAPABILITY_INTERNET));
+ assertFalse(getNetworkCapabilities().hasCapability(NET_CAPABILITY_INTERNET));
- NetworkCallback callback = null;
+ ConnectivityManager.NetworkCallback callback = null;
final ConditionVariable validatedCv = new ConditionVariable();
if (validated) {
setNetworkValid();
NetworkRequest request = new NetworkRequest.Builder()
- .addTransportType(mNetworkCapabilities.getTransportTypes()[0])
+ .addTransportType(getNetworkCapabilities().getTransportTypes()[0])
.clearCapabilities()
.build();
- callback = new NetworkCallback() {
+ callback = new ConnectivityManager.NetworkCallback() {
public void onCapabilitiesChanged(Network network,
NetworkCapabilities networkCapabilities) {
if (network.equals(getNetwork()) &&
- networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED)) {
+ networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED)) {
validatedCv.open();
}
}
@@ -763,47 +631,29 @@
connect(false);
}
- public void suspend() {
- mNetworkInfo.setDetailedState(DetailedState.SUSPENDED, null, null);
- mNetworkAgent.sendNetworkInfo(mNetworkInfo);
+ void setNetworkValid() {
+ mNmValidationResult = VALIDATION_RESULT_VALID;
+ mNmValidationRedirectUrl = null;
}
- public void resume() {
- mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, null);
- mNetworkAgent.sendNetworkInfo(mNetworkInfo);
+ void setNetworkInvalid() {
+ mNmValidationResult = VALIDATION_RESULT_INVALID;
+ mNmValidationRedirectUrl = null;
}
- public void disconnect() {
- mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, null);
- mNetworkAgent.sendNetworkInfo(mNetworkInfo);
+ void setNetworkPortal(String redirectUrl) {
+ setNetworkInvalid();
+ mNmValidationRedirectUrl = redirectUrl;
}
- public Network getNetwork() {
- return new Network(mNetworkAgent.netId);
+ void setNetworkPartial() {
+ mNmValidationResult = VALIDATION_RESULT_PARTIAL;
+ mNmValidationRedirectUrl = null;
}
- public ConditionVariable getPreventReconnectReceived() {
- return mPreventReconnectReceived;
- }
-
- public ConditionVariable getDisconnectedCV() {
- return mDisconnected;
- }
-
- public void sendLinkProperties(LinkProperties lp) {
- mNetworkAgent.sendLinkProperties(lp);
- }
-
- public void setStartKeepaliveError(int error) {
- mStartKeepaliveError = error;
- }
-
- public void setStopKeepaliveError(int error) {
- mStopKeepaliveError = error;
- }
-
- public void setExpectedKeepaliveSlot(Integer slot) {
- mExpectedKeepaliveSlot = slot;
+ void setNetworkPartialValid() {
+ mNmValidationResult = VALIDATION_RESULT_PARTIAL | VALIDATION_RESULT_VALID;
+ mNmValidationRedirectUrl = null;
}
public String waitForRedirectUrl() {
@@ -811,12 +661,12 @@
return mRedirectUrl;
}
- public NetworkAgent getNetworkAgent() {
- return mNetworkAgent;
+ public void expectDisconnected() {
+ expectDisconnected(TIMEOUT_MS);
}
- public NetworkCapabilities getNetworkCapabilities() {
- return mNetworkCapabilities;
+ public void expectPreventReconnectReceived() {
+ expectPreventReconnectReceived(TIMEOUT_MS);
}
}
@@ -995,15 +845,15 @@
private boolean mConnected = false;
// Careful ! This is different from mNetworkAgent, because MockNetworkAgent does
// not inherit from NetworkAgent.
- private MockNetworkAgent mMockNetworkAgent;
+ private TestNetworkAgentWrapper mMockNetworkAgent;
public MockVpn(int userId) {
super(startHandlerThreadAndReturnLooper(), mServiceContext, mNetworkManagementService,
userId);
}
- public void setNetworkAgent(MockNetworkAgent agent) {
- waitForIdle(agent, TIMEOUT_MS);
+ public void setNetworkAgent(TestNetworkAgentWrapper agent) {
+ agent.waitForIdle(TIMEOUT_MS);
mMockNetworkAgent = agent;
mNetworkAgent = agent.getNetworkAgent();
mNetworkCapabilities.set(agent.getNetworkCapabilities());
@@ -1070,187 +920,45 @@
}
}
- private class FakeWakeupMessage extends WakeupMessage {
- private static final int UNREASONABLY_LONG_WAIT = 1000;
-
- public FakeWakeupMessage(Context context, Handler handler, String cmdName, int cmd) {
- super(context, handler, cmdName, cmd);
- }
-
- public FakeWakeupMessage(Context context, Handler handler, String cmdName, int cmd,
- int arg1, int arg2, Object obj) {
- super(context, handler, cmdName, cmd, arg1, arg2, obj);
- }
-
- @Override
- public void schedule(long when) {
- long delayMs = when - SystemClock.elapsedRealtime();
- if (delayMs < 0) delayMs = 0;
- if (delayMs > UNREASONABLY_LONG_WAIT) {
- fail("Attempting to send msg more than " + UNREASONABLY_LONG_WAIT +
- "ms into the future: " + delayMs);
- }
- Message msg = mHandler.obtainMessage(mCmd, mArg1, mArg2, mObj);
- mHandler.sendMessageDelayed(msg, delayMs);
- }
-
- @Override
- public void cancel() {
- mHandler.removeMessages(mCmd, mObj);
- }
-
- @Override
- public void onAlarm() {
- throw new AssertionError("Should never happen. Update this fake.");
+ private void mockVpn(int uid) {
+ synchronized (mService.mVpns) {
+ int userId = UserHandle.getUserId(uid);
+ mMockVpn = new MockVpn(userId);
+ // This has no effect unless the VPN is actually connected, because things like
+ // getActiveNetworkForUidInternal call getNetworkAgentInfoForNetId on the VPN
+ // netId, and check if that network is actually connected.
+ mService.mVpns.put(userId, mMockVpn);
}
}
- private class WrappedMultinetworkPolicyTracker extends MultinetworkPolicyTracker {
- public volatile boolean configRestrictsAvoidBadWifi;
- public volatile int configMeteredMultipathPreference;
+ private void setUidRulesChanged(int uidRules) throws RemoteException {
+ mPolicyListener.onUidRulesChanged(Process.myUid(), uidRules);
+ }
- public WrappedMultinetworkPolicyTracker(Context c, Handler h, Runnable r) {
+ private void setRestrictBackgroundChanged(boolean restrictBackground) throws RemoteException {
+ mPolicyListener.onRestrictBackgroundChanged(restrictBackground);
+ }
+
+ private Nat464Xlat getNat464Xlat(NetworkAgentWrapper mna) {
+ return mService.getNetworkAgentInfoForNetwork(mna.getNetwork()).clatd;
+ }
+
+ private static class WrappedMultinetworkPolicyTracker extends MultinetworkPolicyTracker {
+ volatile boolean mConfigRestrictsAvoidBadWifi;
+ volatile int mConfigMeteredMultipathPreference;
+
+ WrappedMultinetworkPolicyTracker(Context c, Handler h, Runnable r) {
super(c, h, r);
}
@Override
public boolean configRestrictsAvoidBadWifi() {
- return configRestrictsAvoidBadWifi;
+ return mConfigRestrictsAvoidBadWifi;
}
@Override
public int configMeteredMultipathPreference() {
- return configMeteredMultipathPreference;
- }
- }
-
- private class WrappedConnectivityService extends ConnectivityService {
- public WrappedMultinetworkPolicyTracker wrappedMultinetworkPolicyTracker;
- private MockableSystemProperties mSystemProperties;
-
- public WrappedConnectivityService(Context context, INetworkManagementService netManager,
- INetworkStatsService statsService, INetworkPolicyManager policyManager,
- IpConnectivityLog log, INetd netd, IDnsResolver dnsResolver) {
- super(context, netManager, statsService, policyManager, dnsResolver, log, netd);
- mNetd = netd;
- mLingerDelayMs = TEST_LINGER_DELAY_MS;
- }
-
- @Override
- protected MockableSystemProperties getSystemProperties() {
- // Minimal approach to overriding system properties: let most calls fall through to real
- // device values, and only override ones values that are important to this test.
- mSystemProperties = spy(new MockableSystemProperties());
- when(mSystemProperties.getInt("net.tcp.default_init_rwnd", 0)).thenReturn(0);
- when(mSystemProperties.getBoolean("ro.radio.noril", false)).thenReturn(false);
- return mSystemProperties;
- }
-
- @Override
- protected Tethering makeTethering() {
- return mock(Tethering.class);
- }
-
- @Override
- protected ProxyTracker makeProxyTracker() {
- return mock(ProxyTracker.class);
- }
-
- @Override
- protected int reserveNetId() {
- while (true) {
- final int netId = super.reserveNetId();
-
- // Don't overlap test NetIDs with real NetIDs as binding sockets to real networks
- // can have odd side-effects, like network validations succeeding.
- Context context = InstrumentationRegistry.getContext();
- final Network[] networks = ConnectivityManager.from(context).getAllNetworks();
- boolean overlaps = false;
- for (Network network : networks) {
- if (netId == network.netId) {
- overlaps = true;
- break;
- }
- }
- if (overlaps) continue;
-
- return netId;
- }
- }
-
- @Override
- protected boolean queryUserAccess(int uid, int netId) {
- return true;
- }
-
- public Nat464Xlat getNat464Xlat(MockNetworkAgent mna) {
- return getNetworkAgentInfoForNetwork(mna.getNetwork()).clatd;
- }
-
- @Override
- public MultinetworkPolicyTracker createMultinetworkPolicyTracker(
- Context c, Handler h, Runnable r) {
- final WrappedMultinetworkPolicyTracker tracker = new WrappedMultinetworkPolicyTracker(c, h, r);
- return tracker;
- }
-
- public WrappedMultinetworkPolicyTracker getMultinetworkPolicyTracker() {
- return (WrappedMultinetworkPolicyTracker) mMultinetworkPolicyTracker;
- }
-
- @Override
- protected NetworkStackClient getNetworkStack() {
- return mNetworkStack;
- }
-
- @Override
- public WakeupMessage makeWakeupMessage(
- Context context, Handler handler, String cmdName, int cmd, Object obj) {
- return new FakeWakeupMessage(context, handler, cmdName, cmd, 0, 0, obj);
- }
-
- @Override
- public boolean hasService(String name) {
- // Currenty, the only relevant service that ConnectivityService checks for is
- // ETHERNET_SERVICE.
- return Context.ETHERNET_SERVICE.equals(name);
- }
-
- @Override
- protected IpConnectivityMetrics.Logger metricsLogger() {
- return mMetricsService;
- }
-
- @Override
- protected void registerNetdEventCallback() {
- }
-
- public void mockVpn(int uid) {
- synchronized (mVpns) {
- int userId = UserHandle.getUserId(uid);
- mMockVpn = new MockVpn(userId);
- // This has no effect unless the VPN is actually connected, because things like
- // getActiveNetworkForUidInternal call getNetworkAgentInfoForNetId on the VPN
- // netId, and check if that network is actually connected.
- mVpns.put(userId, mMockVpn);
- }
- }
-
- public void waitForIdle(int timeoutMs) {
- HandlerUtilsKt.waitForIdle(mHandlerThread, timeoutMs);
- }
-
- public void waitForIdle() {
- waitForIdle(TIMEOUT_MS);
- }
-
- public void setUidRulesChanged(int uidRules) throws RemoteException {
- mPolicyListener.onUidRulesChanged(Process.myUid(), uidRules);
- }
-
- public void setRestrictBackgroundChanged(boolean restrictBackground)
- throws RemoteException {
- mPolicyListener.onRestrictBackgroundChanged(restrictBackground);
+ return mConfigMeteredMultipathPreference;
}
}
@@ -1296,13 +1004,22 @@
LocalServices.addService(
NetworkPolicyManagerInternal.class, mock(NetworkPolicyManagerInternal.class));
- mService = new WrappedConnectivityService(mServiceContext,
+ mAlarmManagerThread = new HandlerThread("TestAlarmManager");
+ mAlarmManagerThread.start();
+ initAlarmManager(mAlarmManager, mAlarmManagerThread.getThreadHandler());
+
+ mCsHandlerThread = new HandlerThread("TestConnectivityService");
+ final ConnectivityService.Dependencies deps = makeDependencies();
+ mService = new ConnectivityService(mServiceContext,
mNetworkManagementService,
mStatsService,
mNpm,
+ mMockDnsResolver,
mock(IpConnectivityLog.class),
mMockNetd,
- mMockDnsResolver);
+ deps);
+ mService.mLingerDelayMs = TEST_LINGER_DELAY_MS;
+ verify(deps).makeMultinetworkPolicyTracker(any(), any(), any());
final ArgumentCaptor<INetworkPolicyListener> policyListenerCaptor =
ArgumentCaptor.forClass(INetworkPolicyListener.class);
@@ -1313,7 +1030,7 @@
// getSystemService() correctly.
mCm = new WrappedConnectivityManager(InstrumentationRegistry.getContext(), mService);
mService.systemReady();
- mService.mockVpn(Process.myUid());
+ mockVpn(Process.myUid());
mCm.bindProcessToNetwork(null);
// Ensure that the default setting for Captive Portals is used for most tests
@@ -1322,6 +1039,57 @@
setPrivateDnsSettings(PRIVATE_DNS_MODE_OFF, "ignored.example.com");
}
+ private ConnectivityService.Dependencies makeDependencies() {
+ final MockableSystemProperties systemProperties = spy(new MockableSystemProperties());
+ when(systemProperties.getInt("net.tcp.default_init_rwnd", 0)).thenReturn(0);
+ when(systemProperties.getBoolean("ro.radio.noril", false)).thenReturn(false);
+
+ final ConnectivityService.Dependencies deps = mock(ConnectivityService.Dependencies.class);
+ doReturn(mCsHandlerThread).when(deps).makeHandlerThread();
+ doReturn(new TestNetIdManager()).when(deps).makeNetIdManager();
+ doReturn(mNetworkStack).when(deps).getNetworkStack();
+ doReturn(systemProperties).when(deps).getSystemProperties();
+ doReturn(mock(Tethering.class)).when(deps).makeTethering(any(), any(), any(), any(), any());
+ doReturn(mock(ProxyTracker.class)).when(deps).makeProxyTracker(any(), any());
+ doReturn(mMetricsService).when(deps).getMetricsLogger();
+ doReturn(true).when(deps).queryUserAccess(anyInt(), anyInt());
+ doReturn(mIpConnectivityMetrics).when(deps).getIpConnectivityMetrics();
+ doReturn(true).when(deps).hasService(Context.ETHERNET_SERVICE);
+ doAnswer(inv -> {
+ mPolicyTracker = new WrappedMultinetworkPolicyTracker(
+ inv.getArgument(0), inv.getArgument(1), inv.getArgument(2));
+ return mPolicyTracker;
+ }).when(deps).makeMultinetworkPolicyTracker(any(), any(), any());
+
+ return deps;
+ }
+
+ private static void initAlarmManager(final AlarmManager am, final Handler alarmHandler) {
+ doAnswer(inv -> {
+ final long when = inv.getArgument(1);
+ final WakeupMessage wakeupMsg = inv.getArgument(3);
+ final Handler handler = inv.getArgument(4);
+
+ long delayMs = when - SystemClock.elapsedRealtime();
+ if (delayMs < 0) delayMs = 0;
+ if (delayMs > UNREASONABLY_LONG_ALARM_WAIT_MS) {
+ fail("Attempting to send msg more than " + UNREASONABLY_LONG_ALARM_WAIT_MS
+ + "ms into the future: " + delayMs);
+ }
+ alarmHandler.postDelayed(() -> handler.post(wakeupMsg::onAlarm), wakeupMsg /* token */,
+ delayMs);
+
+ return null;
+ }).when(am).setExact(eq(AlarmManager.ELAPSED_REALTIME_WAKEUP), anyLong(), anyString(),
+ any(WakeupMessage.class), any());
+
+ doAnswer(inv -> {
+ final WakeupMessage wakeupMsg = inv.getArgument(0);
+ alarmHandler.removeCallbacksAndMessages(wakeupMsg /* token */);
+ return null;
+ }).when(am).cancel(any(WakeupMessage.class));
+ }
+
@After
public void tearDown() throws Exception {
setAlwaysOnNetworks(false);
@@ -1338,6 +1106,9 @@
mEthernetNetworkAgent = null;
}
FakeSettingsProvider.clearSettingsProvider();
+
+ mCsHandlerThread.quitSafely();
+ mAlarmManagerThread.quitSafely();
}
private void mockDefaultPackages() throws Exception {
@@ -1357,21 +1128,6 @@
}));
}
- private static int transportToLegacyType(int transport) {
- switch (transport) {
- case TRANSPORT_ETHERNET:
- return TYPE_ETHERNET;
- case TRANSPORT_WIFI:
- return TYPE_WIFI;
- case TRANSPORT_CELLULAR:
- return TYPE_MOBILE;
- case TRANSPORT_VPN:
- return TYPE_VPN;
- default:
- return TYPE_NONE;
- }
- }
-
private void verifyActiveNetwork(int transport) {
// Test getActiveNetworkInfo()
assertNotNull(mCm.getActiveNetworkInfo());
@@ -1449,8 +1205,8 @@
@Test
public void testLingering() throws Exception {
verifyNoNetwork();
- mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
- mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+ mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
+ mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
assertNull(mCm.getActiveNetworkInfo());
assertNull(mCm.getActiveNetwork());
// Test bringing up validated cellular.
@@ -1474,7 +1230,7 @@
assertTrue(mCm.getAllNetworks()[0].equals(mCellNetworkAgent.getNetwork()) ||
mCm.getAllNetworks()[1].equals(mCellNetworkAgent.getNetwork()));
// Test cellular linger timeout.
- waitFor(mCellNetworkAgent.getDisconnectedCV());
+ mCellNetworkAgent.expectDisconnected();
waitForIdle();
assertLength(1, mCm.getAllNetworks());
verifyActiveNetwork(TRANSPORT_WIFI);
@@ -1490,13 +1246,13 @@
@Test
public void testValidatedCellularOutscoresUnvalidatedWiFi() throws Exception {
// Test bringing up unvalidated WiFi
- mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+ mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
ConditionVariable cv = waitForConnectivityBroadcasts(1);
mWiFiNetworkAgent.connect(false);
waitFor(cv);
verifyActiveNetwork(TRANSPORT_WIFI);
// Test bringing up unvalidated cellular
- mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
+ mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
mCellNetworkAgent.connect(false);
waitForIdle();
verifyActiveNetwork(TRANSPORT_WIFI);
@@ -1505,7 +1261,7 @@
waitForIdle();
verifyActiveNetwork(TRANSPORT_WIFI);
// Test bringing up validated cellular
- mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
+ mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
cv = waitForConnectivityBroadcasts(2);
mCellNetworkAgent.connect(true);
waitFor(cv);
@@ -1525,13 +1281,13 @@
@Test
public void testUnvalidatedWifiOutscoresUnvalidatedCellular() throws Exception {
// Test bringing up unvalidated cellular.
- mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
+ mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
ConditionVariable cv = waitForConnectivityBroadcasts(1);
mCellNetworkAgent.connect(false);
waitFor(cv);
verifyActiveNetwork(TRANSPORT_CELLULAR);
// Test bringing up unvalidated WiFi.
- mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+ mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
cv = waitForConnectivityBroadcasts(2);
mWiFiNetworkAgent.connect(false);
waitFor(cv);
@@ -1551,7 +1307,7 @@
@Test
public void testUnlingeringDoesNotValidate() throws Exception {
// Test bringing up unvalidated WiFi.
- mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+ mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
ConditionVariable cv = waitForConnectivityBroadcasts(1);
mWiFiNetworkAgent.connect(false);
waitFor(cv);
@@ -1559,7 +1315,7 @@
assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
NET_CAPABILITY_VALIDATED));
// Test bringing up validated cellular.
- mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
+ mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
cv = waitForConnectivityBroadcasts(2);
mCellNetworkAgent.connect(true);
waitFor(cv);
@@ -1579,13 +1335,13 @@
@Test
public void testCellularOutscoresWeakWifi() throws Exception {
// Test bringing up validated cellular.
- mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
+ mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
ConditionVariable cv = waitForConnectivityBroadcasts(1);
mCellNetworkAgent.connect(true);
waitFor(cv);
verifyActiveNetwork(TRANSPORT_CELLULAR);
// Test bringing up validated WiFi.
- mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+ mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
cv = waitForConnectivityBroadcasts(2);
mWiFiNetworkAgent.connect(true);
waitFor(cv);
@@ -1606,45 +1362,41 @@
public void testReapingNetwork() throws Exception {
// Test bringing up WiFi without NET_CAPABILITY_INTERNET.
// Expect it to be torn down immediately because it satisfies no requests.
- mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
- ConditionVariable cv = mWiFiNetworkAgent.getDisconnectedCV();
+ mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
mWiFiNetworkAgent.connectWithoutInternet();
- waitFor(cv);
+ mWiFiNetworkAgent.expectDisconnected();
// Test bringing up cellular without NET_CAPABILITY_INTERNET.
// Expect it to be torn down immediately because it satisfies no requests.
- mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
- cv = mCellNetworkAgent.getDisconnectedCV();
+ mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
mCellNetworkAgent.connectWithoutInternet();
- waitFor(cv);
+ mCellNetworkAgent.expectDisconnected();
// Test bringing up validated WiFi.
- mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
- cv = waitForConnectivityBroadcasts(1);
+ mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+ final ConditionVariable cv = waitForConnectivityBroadcasts(1);
mWiFiNetworkAgent.connect(true);
waitFor(cv);
verifyActiveNetwork(TRANSPORT_WIFI);
// Test bringing up unvalidated cellular.
// Expect it to be torn down because it could never be the highest scoring network
// satisfying the default request even if it validated.
- mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
- cv = mCellNetworkAgent.getDisconnectedCV();
+ mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
mCellNetworkAgent.connect(false);
- waitFor(cv);
+ mCellNetworkAgent.expectDisconnected();
verifyActiveNetwork(TRANSPORT_WIFI);
- cv = mWiFiNetworkAgent.getDisconnectedCV();
mWiFiNetworkAgent.disconnect();
- waitFor(cv);
+ mWiFiNetworkAgent.expectDisconnected();
}
@Test
public void testCellularFallback() throws Exception {
// Test bringing up validated cellular.
- mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
+ mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
ConditionVariable cv = waitForConnectivityBroadcasts(1);
mCellNetworkAgent.connect(true);
waitFor(cv);
verifyActiveNetwork(TRANSPORT_CELLULAR);
// Test bringing up validated WiFi.
- mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+ mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
cv = waitForConnectivityBroadcasts(2);
mWiFiNetworkAgent.connect(true);
waitFor(cv);
@@ -1676,13 +1428,13 @@
@Test
public void testWiFiFallback() throws Exception {
// Test bringing up unvalidated WiFi.
- mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+ mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
ConditionVariable cv = waitForConnectivityBroadcasts(1);
mWiFiNetworkAgent.connect(false);
waitFor(cv);
verifyActiveNetwork(TRANSPORT_WIFI);
// Test bringing up validated cellular.
- mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
+ mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
cv = waitForConnectivityBroadcasts(2);
mCellNetworkAgent.connect(true);
waitFor(cv);
@@ -1760,7 +1512,7 @@
// Test unvalidated networks
ConditionVariable cv = waitForConnectivityBroadcasts(1);
- mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
+ mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
mCellNetworkAgent.connect(false);
genericNetworkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
cellNetworkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
@@ -1775,7 +1527,7 @@
assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
cv = waitForConnectivityBroadcasts(2);
- mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+ mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
mWiFiNetworkAgent.connect(false);
genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
wifiNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
@@ -1799,7 +1551,7 @@
assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
// Test validated networks
- mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
+ mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
mCellNetworkAgent.connect(true);
genericNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
@@ -1812,7 +1564,7 @@
assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
- mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+ mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
mWiFiNetworkAgent.connect(true);
genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
genericNetworkCallback.expectCallback(CallbackRecord.LOSING, mCellNetworkAgent);
@@ -1850,9 +1602,9 @@
TestNetworkCallback defaultCallback = new TestNetworkCallback();
mCm.registerDefaultNetworkCallback(defaultCallback);
- mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
- mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
- mEthernetNetworkAgent = new MockNetworkAgent(TRANSPORT_ETHERNET);
+ mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
+ mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+ mEthernetNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET);
mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
@@ -1891,7 +1643,7 @@
assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
for (int i = 0; i < 4; i++) {
- MockNetworkAgent oldNetwork, newNetwork;
+ TestNetworkAgentWrapper oldNetwork, newNetwork;
if (i % 2 == 0) {
mWiFiNetworkAgent.adjustScore(-15);
oldNetwork = mWiFiNetworkAgent;
@@ -1943,7 +1695,7 @@
mCm.registerNetworkCallback(request, callback);
- mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
+ mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
mCellNetworkAgent.connect(false); // Score: 10
callback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
@@ -1952,7 +1704,7 @@
// Bring up wifi with a score of 20.
// Cell stays up because it would satisfy the default request if it validated.
- mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+ mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
mWiFiNetworkAgent.connect(false); // Score: 20
callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
@@ -1968,7 +1720,7 @@
// Bring up wifi with a score of 70.
// Cell is lingered because it would not satisfy any request, even if it validated.
- mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+ mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
mWiFiNetworkAgent.adjustScore(50);
mWiFiNetworkAgent.connect(false); // Score: 70
callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
@@ -1987,7 +1739,7 @@
// Bring up wifi, then validate it. Previous versions would immediately tear down cell, but
// it's arguably correct to linger it, since it was the default network before it validated.
- mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+ mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
mWiFiNetworkAgent.connect(true);
callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
// TODO: Investigate sending validated before losing.
@@ -2008,12 +1760,12 @@
assertEquals(null, mCm.getActiveNetwork());
// If a network is lingering, and we add and remove a request from it, resume lingering.
- mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
+ mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
mCellNetworkAgent.connect(true);
callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
- mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+ mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
mWiFiNetworkAgent.connect(true);
defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
@@ -2044,7 +1796,7 @@
mCm.requestNetwork(cellRequest, noopCallback);
// Now connect wifi, and expect it to become the default network.
- mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+ mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
mWiFiNetworkAgent.connect(true);
callback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
@@ -2065,7 +1817,7 @@
TestNetworkCallback trackDefaultCallback = new TestNetworkCallback();
mCm.registerDefaultNetworkCallback(trackDefaultCallback);
trackDefaultCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
- mEthernetNetworkAgent = new MockNetworkAgent(TRANSPORT_ETHERNET);
+ mEthernetNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET);
mEthernetNetworkAgent.connect(true);
callback.expectAvailableCallbacksUnvalidated(mEthernetNetworkAgent);
callback.expectCallback(CallbackRecord.LOSING, mWiFiNetworkAgent);
@@ -2100,8 +1852,8 @@
TestNetworkCallback defaultCallback = new TestNetworkCallback();
mCm.registerDefaultNetworkCallback(defaultCallback);
- mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
- mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+ mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
+ mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
mCellNetworkAgent.connect(true);
callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
@@ -2142,12 +1894,12 @@
mCm.registerNetworkCallback(request, callback);
// Bring up validated cell.
- mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
+ mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
mCellNetworkAgent.connect(true);
callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
// Bring up unvalidated wifi with explicitlySelected=true.
- mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+ mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
mWiFiNetworkAgent.explicitlySelected(true, false);
mWiFiNetworkAgent.connect(false);
callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
@@ -2170,7 +1922,7 @@
// Disconnect wifi, and then reconnect, again with explicitlySelected=true.
mWiFiNetworkAgent.disconnect();
callback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
- mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+ mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
mWiFiNetworkAgent.explicitlySelected(true, false);
mWiFiNetworkAgent.connect(false);
callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
@@ -2181,7 +1933,7 @@
callback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
// Reconnect, again with explicitlySelected=true, but this time validate.
- mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+ mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
mWiFiNetworkAgent.explicitlySelected(true, false);
mWiFiNetworkAgent.connect(true);
callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
@@ -2191,7 +1943,7 @@
// BUG: the network will no longer linger, even though it's validated and outscored.
// TODO: fix this.
- mEthernetNetworkAgent = new MockNetworkAgent(TRANSPORT_ETHERNET);
+ mEthernetNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET);
mEthernetNetworkAgent.connect(true);
callback.expectAvailableThenValidatedCallbacks(mEthernetNetworkAgent);
assertEquals(mEthernetNetworkAgent.getNetwork(), mCm.getActiveNetwork());
@@ -2202,7 +1954,7 @@
// wifi immediately.
mWiFiNetworkAgent.disconnect();
callback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
- mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+ mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
mWiFiNetworkAgent.explicitlySelected(true, true);
mWiFiNetworkAgent.connect(false);
callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
@@ -2215,7 +1967,7 @@
// Check that the network is not scored specially and that the device prefers cell data.
mWiFiNetworkAgent.disconnect();
callback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
- mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+ mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
mWiFiNetworkAgent.explicitlySelected(false, true);
mWiFiNetworkAgent.connect(false);
callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
@@ -2277,7 +2029,7 @@
assertTrue(testFactory.getMyStartRequested());
// Now bring in a higher scored network.
- MockNetworkAgent testAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
+ TestNetworkAgentWrapper testAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
// Rather than create a validated network which complicates things by registering it's
// own NetworkRequest during startup, just bump up the score to cancel out the
// unvalidated penalty.
@@ -2371,18 +2123,17 @@
@Test
public void testMMSonWiFi() throws Exception {
// Test bringing up cellular without MMS NetworkRequest gets reaped
- mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
+ mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS);
- ConditionVariable cv = mCellNetworkAgent.getDisconnectedCV();
mCellNetworkAgent.connectWithoutInternet();
- waitFor(cv);
+ mCellNetworkAgent.expectDisconnected();
waitForIdle();
assertEmpty(mCm.getAllNetworks());
verifyNoNetwork();
// Test bringing up validated WiFi.
- mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
- cv = waitForConnectivityBroadcasts(1);
+ mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+ final ConditionVariable cv = waitForConnectivityBroadcasts(1);
mWiFiNetworkAgent.connect(true);
waitFor(cv);
verifyActiveNetwork(TRANSPORT_WIFI);
@@ -2394,23 +2145,22 @@
mCm.requestNetwork(builder.build(), networkCallback);
// Test bringing up unvalidated cellular with MMS
- mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
+ mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS);
mCellNetworkAgent.connectWithoutInternet();
networkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
verifyActiveNetwork(TRANSPORT_WIFI);
// Test releasing NetworkRequest disconnects cellular with MMS
- cv = mCellNetworkAgent.getDisconnectedCV();
mCm.unregisterNetworkCallback(networkCallback);
- waitFor(cv);
+ mCellNetworkAgent.expectDisconnected();
verifyActiveNetwork(TRANSPORT_WIFI);
}
@Test
public void testMMSonCell() throws Exception {
// Test bringing up cellular without MMS
- mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
+ mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
ConditionVariable cv = waitForConnectivityBroadcasts(1);
mCellNetworkAgent.connect(false);
waitFor(cv);
@@ -2423,16 +2173,16 @@
mCm.requestNetwork(builder.build(), networkCallback);
// Test bringing up MMS cellular network
- MockNetworkAgent mmsNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
+ TestNetworkAgentWrapper
+ mmsNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
mmsNetworkAgent.addCapability(NET_CAPABILITY_MMS);
mmsNetworkAgent.connectWithoutInternet();
networkCallback.expectAvailableCallbacksUnvalidated(mmsNetworkAgent);
verifyActiveNetwork(TRANSPORT_CELLULAR);
// Test releasing MMS NetworkRequest does not disconnect main cellular NetworkAgent
- cv = mmsNetworkAgent.getDisconnectedCV();
mCm.unregisterNetworkCallback(networkCallback);
- waitFor(cv);
+ mmsNetworkAgent.expectDisconnected();
verifyActiveNetwork(TRANSPORT_CELLULAR);
}
@@ -2446,12 +2196,12 @@
mCm.registerNetworkCallback(request, callback);
// Bring up validated mobile data.
- mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
+ mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
mCellNetworkAgent.connect(true);
callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
// Bring up wifi with partial connectivity.
- mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+ mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
mWiFiNetworkAgent.connectWithPartialConnectivity();
callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
callback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY, mWiFiNetworkAgent);
@@ -2484,7 +2234,7 @@
// Disconnect and reconnect wifi with partial connectivity again.
mWiFiNetworkAgent.disconnect();
callback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
- mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+ mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
mWiFiNetworkAgent.connectWithPartialConnectivity();
callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
callback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY, mWiFiNetworkAgent);
@@ -2500,7 +2250,7 @@
// If user accepted partial connectivity before, and device reconnects to that network
// again, but now the network has full connectivity. The network shouldn't contain
// NET_CAPABILITY_PARTIAL_CONNECTIVITY.
- mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+ mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
// acceptUnvalidated is also used as setting for accepting partial networks.
mWiFiNetworkAgent.explicitlySelected(true /* explicitlySelected */,
true /* acceptUnvalidated */);
@@ -2524,7 +2274,7 @@
// The user accepted partial connectivity and selected "don't ask again". Now the user
// reconnects to the partial connectivity network. Switch to wifi as soon as partial
// connectivity is detected.
- mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+ mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
mWiFiNetworkAgent.explicitlySelected(true /* explicitlySelected */,
true /* acceptUnvalidated */);
mWiFiNetworkAgent.connectWithPartialConnectivity();
@@ -2548,7 +2298,7 @@
// If the user accepted partial connectivity, and the device auto-reconnects to the partial
// connectivity network, it should contain both PARTIAL_CONNECTIVITY and VALIDATED.
- mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+ mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
mWiFiNetworkAgent.explicitlySelected(false /* explicitlySelected */,
true /* acceptUnvalidated */);
@@ -2580,7 +2330,7 @@
// Bring up a network with a captive portal.
// Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
- mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+ mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
String redirectUrl = "http://android.com/path";
mWiFiNetworkAgent.connectWithCaptivePortal(redirectUrl);
captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
@@ -2629,7 +2379,7 @@
// Bring up a network with a captive portal.
// Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
- mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+ mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
String firstRedirectUrl = "http://example.com/firstPath";
mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl);
captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
@@ -2642,7 +2392,7 @@
// Bring up a network with a captive portal.
// Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
- mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+ mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
String secondRedirectUrl = "http://example.com/secondPath";
mWiFiNetworkAgent.connectWithCaptivePortal(secondRedirectUrl);
captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
@@ -2680,7 +2430,7 @@
mCm.registerNetworkCallback(validatedRequest, validatedCallback);
// Bring up wifi.
- mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+ mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
mWiFiNetworkAgent.connect(true);
validatedCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Network wifiNetwork = mWiFiNetworkAgent.getNetwork();
@@ -2740,14 +2490,12 @@
setCaptivePortalMode(Settings.Global.CAPTIVE_PORTAL_MODE_AVOID);
// Bring up a network with a captive portal.
// Expect it to fail to connect and not result in any callbacks.
- mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+ mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
String firstRedirectUrl = "http://example.com/firstPath";
- ConditionVariable disconnectCv = mWiFiNetworkAgent.getDisconnectedCV();
- ConditionVariable avoidCv = mWiFiNetworkAgent.getPreventReconnectReceived();
mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl);
- waitFor(disconnectCv);
- waitFor(avoidCv);
+ mWiFiNetworkAgent.expectDisconnected();
+ mWiFiNetworkAgent.expectPreventReconnectReceived();
assertNoCallbacks(captivePortalCallback, validatedCallback);
}
@@ -2846,7 +2594,7 @@
LocalStringNetworkSpecifier nsFoo = new LocalStringNetworkSpecifier("foo");
LocalStringNetworkSpecifier nsBar = new LocalStringNetworkSpecifier("bar");
- mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+ mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
mWiFiNetworkAgent.connect(false);
cEmpty1.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
cEmpty2.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
@@ -2973,7 +2721,7 @@
public void writeToParcel(Parcel dest, int flags) {}
}
- mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+ mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
mWiFiNetworkAgent.connect(false);
UidAwareNetworkSpecifier networkSpecifier = new UidAwareNetworkSpecifier();
@@ -3026,14 +2774,14 @@
cellNetworkCallback.assertNoCallback();
// Bring up cell and expect CALLBACK_AVAILABLE.
- mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
+ mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
mCellNetworkAgent.connect(true);
cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
defaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
// Bring up wifi and expect CALLBACK_AVAILABLE.
- mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+ mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
mWiFiNetworkAgent.connect(true);
cellNetworkCallback.assertNoCallback();
defaultNetworkCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
@@ -3046,7 +2794,7 @@
assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
// Bring up cell. Expect no default network callback, since it won't be the default.
- mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
+ mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
mCellNetworkAgent.connect(true);
cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
defaultNetworkCallback.assertNoCallback();
@@ -3065,7 +2813,8 @@
assertEquals(null, mCm.getActiveNetwork());
final int uid = Process.myUid();
- final MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
+ final TestNetworkAgentWrapper
+ vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
final ArraySet<UidRange> ranges = new ArraySet<>();
ranges.add(new UidRange(uid, uid));
mMockVpn.setNetworkAgent(vpnNetworkAgent);
@@ -3090,7 +2839,7 @@
mCm.requestNetwork(cellRequest, cellNetworkCallback);
// Bring up the mobile network.
- mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
+ mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
mCellNetworkAgent.connect(true);
// We should get onAvailable(), onCapabilitiesChanged(), and
@@ -3160,7 +2909,7 @@
waitForIdle();
}
- private boolean isForegroundNetwork(MockNetworkAgent network) {
+ private boolean isForegroundNetwork(TestNetworkAgentWrapper network) {
NetworkCapabilities nc = mCm.getNetworkCapabilities(network.getNetwork());
assertNotNull(nc);
return nc.hasCapability(NET_CAPABILITY_FOREGROUND);
@@ -3179,13 +2928,13 @@
mCm.registerNetworkCallback(request, callback);
mCm.registerNetworkCallback(fgRequest, fgCallback);
- mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
+ mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
mCellNetworkAgent.connect(true);
callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
fgCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
assertTrue(isForegroundNetwork(mCellNetworkAgent));
- mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+ mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
mWiFiNetworkAgent.connect(true);
// When wifi connects, cell lingers.
@@ -3278,7 +3027,7 @@
}
});
- mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
+ mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
// Don't request that the network validate, because otherwise connect() will block until
// the network gets NET_CAPABILITY_VALIDATED, after all the callbacks below have fired,
// and we won't actually measure anything.
@@ -3295,7 +3044,7 @@
onAvailableDispatchingDuration <= CONNECT_TIME_LIMIT_MS);
// Give wifi a high enough score that we'll linger cell when wifi comes up.
- mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+ mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
mWiFiNetworkAgent.adjustScore(40);
mWiFiNetworkAgent.connect(false);
@@ -3338,7 +3087,7 @@
assertTrue(testFactory.getMyStartRequested());
// Bring up wifi. The factory stops looking for a network.
- mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+ mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
// Score 60 - 40 penalty for not validated yet, then 60 when it validates
testFactory.expectAddRequestsWithScores(20, 60);
mWiFiNetworkAgent.connect(true);
@@ -3355,7 +3104,7 @@
// Bring up cell data and check that the factory stops looking.
assertLength(1, mCm.getAllNetworks());
- mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
+ mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
testFactory.expectAddRequestsWithScores(10, 50); // Unvalidated, then validated
mCellNetworkAgent.connect(true);
cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
@@ -3384,48 +3133,46 @@
@Test
public void testAvoidBadWifiSetting() throws Exception {
final ContentResolver cr = mServiceContext.getContentResolver();
- final WrappedMultinetworkPolicyTracker tracker = mService.getMultinetworkPolicyTracker();
final String settingName = Settings.Global.NETWORK_AVOID_BAD_WIFI;
- tracker.configRestrictsAvoidBadWifi = false;
+ mPolicyTracker.mConfigRestrictsAvoidBadWifi = false;
String[] values = new String[] {null, "0", "1"};
for (int i = 0; i < values.length; i++) {
Settings.Global.putInt(cr, settingName, 1);
- tracker.reevaluate();
+ mPolicyTracker.reevaluate();
waitForIdle();
String msg = String.format("config=false, setting=%s", values[i]);
assertTrue(mService.avoidBadWifi());
- assertFalse(msg, tracker.shouldNotifyWifiUnvalidated());
+ assertFalse(msg, mPolicyTracker.shouldNotifyWifiUnvalidated());
}
- tracker.configRestrictsAvoidBadWifi = true;
+ mPolicyTracker.mConfigRestrictsAvoidBadWifi = true;
Settings.Global.putInt(cr, settingName, 0);
- tracker.reevaluate();
+ mPolicyTracker.reevaluate();
waitForIdle();
assertFalse(mService.avoidBadWifi());
- assertFalse(tracker.shouldNotifyWifiUnvalidated());
+ assertFalse(mPolicyTracker.shouldNotifyWifiUnvalidated());
Settings.Global.putInt(cr, settingName, 1);
- tracker.reevaluate();
+ mPolicyTracker.reevaluate();
waitForIdle();
assertTrue(mService.avoidBadWifi());
- assertFalse(tracker.shouldNotifyWifiUnvalidated());
+ assertFalse(mPolicyTracker.shouldNotifyWifiUnvalidated());
Settings.Global.putString(cr, settingName, null);
- tracker.reevaluate();
+ mPolicyTracker.reevaluate();
waitForIdle();
assertFalse(mService.avoidBadWifi());
- assertTrue(tracker.shouldNotifyWifiUnvalidated());
+ assertTrue(mPolicyTracker.shouldNotifyWifiUnvalidated());
}
@Test
public void testAvoidBadWifi() throws Exception {
final ContentResolver cr = mServiceContext.getContentResolver();
- final WrappedMultinetworkPolicyTracker tracker = mService.getMultinetworkPolicyTracker();
// Pretend we're on a carrier that restricts switching away from bad wifi.
- tracker.configRestrictsAvoidBadWifi = true;
+ mPolicyTracker.mConfigRestrictsAvoidBadWifi = true;
// File a request for cell to ensure it doesn't go down.
final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
@@ -3444,17 +3191,17 @@
mCm.registerNetworkCallback(validatedWifiRequest, validatedWifiCallback);
Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 0);
- tracker.reevaluate();
+ mPolicyTracker.reevaluate();
// Bring up validated cell.
- mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
+ mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
mCellNetworkAgent.connect(true);
cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Network cellNetwork = mCellNetworkAgent.getNetwork();
// Bring up validated wifi.
- mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+ mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
mWiFiNetworkAgent.connect(true);
defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
validatedWifiCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
@@ -3476,14 +3223,14 @@
// Simulate switching to a carrier that does not restrict avoiding bad wifi, and expect
// that we switch back to cell.
- tracker.configRestrictsAvoidBadWifi = false;
- tracker.reevaluate();
+ mPolicyTracker.mConfigRestrictsAvoidBadWifi = false;
+ mPolicyTracker.reevaluate();
defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
assertEquals(mCm.getActiveNetwork(), cellNetwork);
// Switch back to a restrictive carrier.
- tracker.configRestrictsAvoidBadWifi = true;
- tracker.reevaluate();
+ mPolicyTracker.mConfigRestrictsAvoidBadWifi = true;
+ mPolicyTracker.reevaluate();
defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
assertEquals(mCm.getActiveNetwork(), wifiNetwork);
@@ -3498,7 +3245,7 @@
// Disconnect and reconnect wifi to clear the one-time switch above.
mWiFiNetworkAgent.disconnect();
- mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+ mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
mWiFiNetworkAgent.connect(true);
defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
validatedWifiCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
@@ -3512,7 +3259,7 @@
// Simulate the user selecting "switch" and checking the don't ask again checkbox.
Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 1);
- tracker.reevaluate();
+ mPolicyTracker.reevaluate();
// We now switch to cell.
defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
@@ -3525,11 +3272,11 @@
// Simulate the user turning the cellular fallback setting off and then on.
// We switch to wifi and then to cell.
Settings.Global.putString(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, null);
- tracker.reevaluate();
+ mPolicyTracker.reevaluate();
defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
assertEquals(mCm.getActiveNetwork(), wifiNetwork);
Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 1);
- tracker.reevaluate();
+ mPolicyTracker.reevaluate();
defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
assertEquals(mCm.getActiveNetwork(), cellNetwork);
@@ -3547,14 +3294,13 @@
@Test
public void testMeteredMultipathPreferenceSetting() throws Exception {
final ContentResolver cr = mServiceContext.getContentResolver();
- final WrappedMultinetworkPolicyTracker tracker = mService.getMultinetworkPolicyTracker();
final String settingName = Settings.Global.NETWORK_METERED_MULTIPATH_PREFERENCE;
for (int config : Arrays.asList(0, 3, 2)) {
for (String setting: Arrays.asList(null, "0", "2", "1")) {
- tracker.configMeteredMultipathPreference = config;
+ mPolicyTracker.mConfigMeteredMultipathPreference = config;
Settings.Global.putString(cr, settingName, setting);
- tracker.reevaluate();
+ mPolicyTracker.reevaluate();
waitForIdle();
final int expected = (setting != null) ? Integer.parseInt(setting) : config;
@@ -3575,7 +3321,7 @@
final TestNetworkCallback networkCallback = new TestNetworkCallback();
mCm.requestNetwork(nr, networkCallback, TEST_REQUEST_TIMEOUT_MS);
- mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+ mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
mWiFiNetworkAgent.connect(false);
networkCallback.expectAvailableCallbacks(mWiFiNetworkAgent, false, false, false,
TEST_CALLBACK_TIMEOUT_MS);
@@ -3595,7 +3341,7 @@
final TestNetworkCallback networkCallback = new TestNetworkCallback();
mCm.requestNetwork(nr, networkCallback, TEST_REQUEST_TIMEOUT_MS);
- mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+ mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
mWiFiNetworkAgent.connect(false);
networkCallback.expectAvailableCallbacks(mWiFiNetworkAgent, false, false, false,
TEST_CALLBACK_TIMEOUT_MS);
@@ -3623,7 +3369,7 @@
networkCallback.expectCallback(CallbackRecord.UNAVAILABLE, null);
// create a network satisfying request - validate that request not triggered
- mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+ mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
mWiFiNetworkAgent.connect(false);
networkCallback.assertNoCallback();
}
@@ -3646,7 +3392,7 @@
networkCallback.assertNoCallback();
// create a network satisfying request - validate that request not triggered
- mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+ mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
mWiFiNetworkAgent.connect(false);
networkCallback.assertNoCallback();
}
@@ -3876,7 +3622,7 @@
assertNull(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()));
}
- mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+ mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
ConditionVariable cv = waitForConnectivityBroadcasts(1);
mWiFiNetworkAgent.connect(true);
waitFor(cv);
@@ -3940,10 +3686,10 @@
callback.expectError(PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED);
// Check that a started keepalive can be stopped.
- mWiFiNetworkAgent.setStartKeepaliveError(PacketKeepalive.SUCCESS);
+ mWiFiNetworkAgent.setStartKeepaliveEvent(PacketKeepalive.SUCCESS);
ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
callback.expectStarted();
- mWiFiNetworkAgent.setStopKeepaliveError(PacketKeepalive.SUCCESS);
+ mWiFiNetworkAgent.setStopKeepaliveEvent(PacketKeepalive.SUCCESS);
ka.stop();
callback.expectStopped();
@@ -3961,7 +3707,7 @@
ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
callback.expectStarted();
mWiFiNetworkAgent.disconnect();
- waitFor(mWiFiNetworkAgent.getDisconnectedCV());
+ mWiFiNetworkAgent.expectDisconnected();
callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK);
// ... and that stopping it after that has no adverse effects.
@@ -3972,7 +3718,7 @@
// Reconnect.
myNet = connectKeepaliveNetwork(lp);
- mWiFiNetworkAgent.setStartKeepaliveError(PacketKeepalive.SUCCESS);
+ mWiFiNetworkAgent.setStartKeepaliveEvent(PacketKeepalive.SUCCESS);
// Check that keepalive slots start from 1 and increment. The first one gets slot 1.
mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
@@ -4092,12 +3838,12 @@
}
// Check that a started keepalive can be stopped.
- mWiFiNetworkAgent.setStartKeepaliveError(SocketKeepalive.SUCCESS);
+ mWiFiNetworkAgent.setStartKeepaliveEvent(SocketKeepalive.SUCCESS);
try (SocketKeepalive ka = mCm.createSocketKeepalive(
myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
ka.start(validKaInterval);
callback.expectStarted();
- mWiFiNetworkAgent.setStopKeepaliveError(SocketKeepalive.SUCCESS);
+ mWiFiNetworkAgent.setStopKeepaliveEvent(SocketKeepalive.SUCCESS);
ka.stop();
callback.expectStopped();
@@ -4137,7 +3883,7 @@
ka.start(validKaInterval);
callback.expectStarted();
mWiFiNetworkAgent.disconnect();
- waitFor(mWiFiNetworkAgent.getDisconnectedCV());
+ mWiFiNetworkAgent.expectDisconnected();
callback.expectError(SocketKeepalive.ERROR_INVALID_NETWORK);
// ... and that stopping it after that has no adverse effects.
@@ -4150,7 +3896,7 @@
// Reconnect.
myNet = connectKeepaliveNetwork(lp);
- mWiFiNetworkAgent.setStartKeepaliveError(SocketKeepalive.SUCCESS);
+ mWiFiNetworkAgent.setStartKeepaliveEvent(SocketKeepalive.SUCCESS);
// Check that keepalive slots start from 1 and increment. The first one gets slot 1.
mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
@@ -4187,7 +3933,7 @@
// assertFalse(isUdpPortInUse(srcPort2));
mWiFiNetworkAgent.disconnect();
- waitFor(mWiFiNetworkAgent.getDisconnectedCV());
+ mWiFiNetworkAgent.expectDisconnected();
mWiFiNetworkAgent = null;
}
@@ -4263,7 +4009,7 @@
testSocketV6.close();
mWiFiNetworkAgent.disconnect();
- waitFor(mWiFiNetworkAgent.getDisconnectedCV());
+ mWiFiNetworkAgent.expectDisconnected();
mWiFiNetworkAgent = null;
}
@@ -4279,8 +4025,8 @@
lp.addLinkAddress(new LinkAddress(myIPv4, 25));
lp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254")));
Network myNet = connectKeepaliveNetwork(lp);
- mWiFiNetworkAgent.setStartKeepaliveError(SocketKeepalive.SUCCESS);
- mWiFiNetworkAgent.setStopKeepaliveError(SocketKeepalive.SUCCESS);
+ mWiFiNetworkAgent.setStartKeepaliveEvent(SocketKeepalive.SUCCESS);
+ mWiFiNetworkAgent.setStopKeepaliveEvent(SocketKeepalive.SUCCESS);
TestSocketKeepaliveCallback callback = new TestSocketKeepaliveCallback(executor);
@@ -4316,7 +4062,7 @@
// assertFalse(isUdpPortInUse(srcPort));
mWiFiNetworkAgent.disconnect();
- waitFor(mWiFiNetworkAgent.getDisconnectedCV());
+ mWiFiNetworkAgent.expectDisconnected();
mWiFiNetworkAgent = null;
}
@@ -4379,9 +4125,9 @@
TestNetworkPinner.pin(mServiceContext, wifiRequest);
assertNull(mCm.getBoundNetworkForProcess());
- mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
+ mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
mCellNetworkAgent.connect(true);
- mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+ mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
mWiFiNetworkAgent.connect(false);
// When wi-fi connects, expect to be pinned.
@@ -4394,7 +4140,7 @@
assertNotPinnedToWifi();
// Reconnecting does not cause the pin to come back.
- mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+ mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
mWiFiNetworkAgent.connect(false);
assertFalse(TestNetworkPinner.awaitPin(100));
assertNotPinnedToWifi();
@@ -4416,14 +4162,14 @@
// Pinning takes effect even if the pinned network is the default when the pin is set...
TestNetworkPinner.pin(mServiceContext, wifiRequest);
- mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+ mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
mWiFiNetworkAgent.connect(false);
assertTrue(TestNetworkPinner.awaitPin(100));
assertPinnedToWifiWithWifiDefault();
// ... and is maintained even when that network is no longer the default.
cv = waitForConnectivityBroadcasts(1);
- mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+ mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
mCellNetworkAgent.connect(true);
waitFor(cv);
assertPinnedToWifiWithCellDefault();
@@ -4526,7 +4272,7 @@
ConditionVariable broadcastCV = waitForConnectivityBroadcasts(1);
verifyNoNetwork();
- MockNetworkAgent wifiAware = new MockNetworkAgent(TRANSPORT_WIFI_AWARE);
+ TestNetworkAgentWrapper wifiAware = new TestNetworkAgentWrapper(TRANSPORT_WIFI_AWARE);
assertNull(mCm.getActiveNetworkInfo());
Network[] allNetworks = mCm.getAllNetworks();
@@ -4599,7 +4345,7 @@
// Verify direct routes are added when network agent is first registered in
// ConnectivityService.
- MockNetworkAgent networkAgent = new MockNetworkAgent(TRANSPORT_WIFI, lp);
+ TestNetworkAgentWrapper networkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, lp);
networkAgent.connect(true);
networkCallback.expectCallback(CallbackRecord.AVAILABLE, networkAgent);
networkCallback.expectCallback(CallbackRecord.NETWORK_CAPS_UPDATED, networkAgent);
@@ -4631,8 +4377,8 @@
@Test
public void testStatsIfacesChanged() throws Exception {
- mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
- mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+ mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
+ mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Network[] onlyCell = new Network[] {mCellNetworkAgent.getNetwork()};
Network[] onlyWifi = new Network[] {mWiFiNetworkAgent.getNetwork()};
@@ -4708,7 +4454,7 @@
// Clear any interactions that occur as a result of CS starting up.
reset(mMockDnsResolver);
- mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
+ mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
waitForIdle();
verify(mMockDnsResolver, never()).setResolverConfiguration(any());
verifyNoMoreInteractions(mMockDnsResolver);
@@ -4791,7 +4537,7 @@
.addTransportType(TRANSPORT_CELLULAR).build();
mCm.requestNetwork(cellRequest, cellNetworkCallback);
- mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
+ mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
waitForIdle();
// CS tells netd about the empty DNS config for this network.
verify(mMockDnsResolver, never()).setResolverConfiguration(any());
@@ -4880,7 +4626,7 @@
.addTransportType(TRANSPORT_CELLULAR).build();
mCm.requestNetwork(cellRequest, cellNetworkCallback);
- mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
+ mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
waitForIdle();
LinkProperties lp = new LinkProperties();
mCellNetworkAgent.sendLinkProperties(lp);
@@ -5015,7 +4761,7 @@
mCm.registerDefaultNetworkCallback(defaultCallback);
defaultCallback.assertNoCallback();
- mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+ mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
mWiFiNetworkAgent.connect(false);
genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
@@ -5025,14 +4771,16 @@
vpnNetworkCallback.assertNoCallback();
assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
- final MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
+ final TestNetworkAgentWrapper
+ vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
final ArraySet<UidRange> ranges = new ArraySet<>();
ranges.add(new UidRange(uid, uid));
mMockVpn.setNetworkAgent(vpnNetworkAgent);
mMockVpn.setUids(ranges);
// VPN networks do not satisfy the default request and are automatically validated
// by NetworkMonitor
- assertFalse(NetworkMonitorUtils.isValidationRequired(vpnNetworkAgent.mNetworkCapabilities));
+ assertFalse(NetworkMonitorUtils.isValidationRequired(
+ vpnNetworkAgent.getNetworkCapabilities()));
vpnNetworkAgent.setNetworkValid();
vpnNetworkAgent.connect(false);
@@ -5110,13 +4858,14 @@
final TestNetworkCallback defaultCallback = new TestNetworkCallback();
mCm.registerDefaultNetworkCallback(defaultCallback);
- mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+ mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
mWiFiNetworkAgent.connect(true);
defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
- MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
+ TestNetworkAgentWrapper
+ vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
final ArraySet<UidRange> ranges = new ArraySet<>();
ranges.add(new UidRange(uid, uid));
mMockVpn.setNetworkAgent(vpnNetworkAgent);
@@ -5140,13 +4889,14 @@
final TestNetworkCallback defaultCallback = new TestNetworkCallback();
mCm.registerDefaultNetworkCallback(defaultCallback);
- mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+ mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
mWiFiNetworkAgent.connect(true);
defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
- MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
+ TestNetworkAgentWrapper
+ vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
final ArraySet<UidRange> ranges = new ArraySet<>();
ranges.add(new UidRange(uid, uid));
mMockVpn.setNetworkAgent(vpnNetworkAgent);
@@ -5170,14 +4920,15 @@
mCm.registerDefaultNetworkCallback(callback);
// Bring up Ethernet.
- mEthernetNetworkAgent = new MockNetworkAgent(TRANSPORT_ETHERNET);
+ mEthernetNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET);
mEthernetNetworkAgent.connect(true);
callback.expectAvailableThenValidatedCallbacks(mEthernetNetworkAgent);
callback.assertNoCallback();
// Bring up a VPN that has the INTERNET capability, initially unvalidated.
final int uid = Process.myUid();
- final MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
+ final TestNetworkAgentWrapper
+ vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
final ArraySet<UidRange> ranges = new ArraySet<>();
ranges.add(new UidRange(uid, uid));
mMockVpn.setNetworkAgent(vpnNetworkAgent);
@@ -5199,9 +4950,10 @@
assertFalse(nc.hasCapability(NET_CAPABILITY_VALIDATED));
assertTrue(nc.hasCapability(NET_CAPABILITY_INTERNET));
- assertFalse(NetworkMonitorUtils.isValidationRequired(vpnNetworkAgent.mNetworkCapabilities));
+ assertFalse(NetworkMonitorUtils.isValidationRequired(
+ vpnNetworkAgent.getNetworkCapabilities()));
assertTrue(NetworkMonitorUtils.isPrivateDnsValidationRequired(
- vpnNetworkAgent.mNetworkCapabilities));
+ vpnNetworkAgent.getNetworkCapabilities()));
// Pretend that the VPN network validates.
vpnNetworkAgent.setNetworkValid();
@@ -5229,7 +4981,8 @@
mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback);
vpnNetworkCallback.assertNoCallback();
- final MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
+ final TestNetworkAgentWrapper
+ vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
final ArraySet<UidRange> ranges = new ArraySet<>();
ranges.add(new UidRange(uid, uid));
mMockVpn.setNetworkAgent(vpnNetworkAgent);
@@ -5246,7 +4999,7 @@
assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_METERED));
// Connect cell and use it as an underlying network.
- mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
+ mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
mCellNetworkAgent.connect(true);
mService.setUnderlyingNetworksForVpn(
@@ -5257,7 +5010,7 @@
&& caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
&& !caps.hasCapability(NET_CAPABILITY_NOT_METERED));
- mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+ mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
mWiFiNetworkAgent.connect(true);
@@ -5327,7 +5080,8 @@
mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback);
vpnNetworkCallback.assertNoCallback();
- final MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
+ final TestNetworkAgentWrapper
+ vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
final ArraySet<UidRange> ranges = new ArraySet<>();
ranges.add(new UidRange(uid, uid));
mMockVpn.setNetworkAgent(vpnNetworkAgent);
@@ -5345,7 +5099,7 @@
assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_METERED));
// Connect to Cell; Cell is the default network.
- mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
+ mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
mCellNetworkAgent.connect(true);
vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
@@ -5354,7 +5108,7 @@
&& !caps.hasCapability(NET_CAPABILITY_NOT_METERED));
// Connect to WiFi; WiFi is the new default.
- mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+ mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
mWiFiNetworkAgent.connect(true);
@@ -5382,7 +5136,7 @@
public void testIsActiveNetworkMeteredOverWifi() throws Exception {
// Returns true by default when no network is available.
assertTrue(mCm.isActiveNetworkMetered());
- mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+ mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
mWiFiNetworkAgent.connect(true);
waitForIdle();
@@ -5394,7 +5148,7 @@
public void testIsActiveNetworkMeteredOverCell() throws Exception {
// Returns true by default when no network is available.
assertTrue(mCm.isActiveNetworkMetered());
- mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
+ mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
mCellNetworkAgent.connect(true);
waitForIdle();
@@ -5406,14 +5160,15 @@
public void testIsActiveNetworkMeteredOverVpnTrackingPlatformDefault() throws Exception {
// Returns true by default when no network is available.
assertTrue(mCm.isActiveNetworkMetered());
- mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
+ mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
mCellNetworkAgent.connect(true);
waitForIdle();
assertTrue(mCm.isActiveNetworkMetered());
// Connect VPN network. By default it is using current default network (Cell).
- MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
+ TestNetworkAgentWrapper
+ vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
final ArraySet<UidRange> ranges = new ArraySet<>();
final int uid = Process.myUid();
ranges.add(new UidRange(uid, uid));
@@ -5429,7 +5184,7 @@
assertTrue(mCm.isActiveNetworkMetered());
// Connect WiFi.
- mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+ mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
mWiFiNetworkAgent.connect(true);
waitForIdle();
@@ -5460,20 +5215,21 @@
public void testIsActiveNetworkMeteredOverVpnSpecifyingUnderlyingNetworks() throws Exception {
// Returns true by default when no network is available.
assertTrue(mCm.isActiveNetworkMetered());
- mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
+ mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
mCellNetworkAgent.connect(true);
waitForIdle();
assertTrue(mCm.isActiveNetworkMetered());
- mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+ mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
mWiFiNetworkAgent.connect(true);
waitForIdle();
assertFalse(mCm.isActiveNetworkMetered());
// Connect VPN network.
- MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
+ TestNetworkAgentWrapper
+ vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
final ArraySet<UidRange> ranges = new ArraySet<>();
final int uid = Process.myUid();
ranges.add(new UidRange(uid, uid));
@@ -5531,14 +5287,15 @@
public void testIsActiveNetworkMeteredOverAlwaysMeteredVpn() throws Exception {
// Returns true by default when no network is available.
assertTrue(mCm.isActiveNetworkMetered());
- mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+ mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
mWiFiNetworkAgent.connect(true);
waitForIdle();
assertFalse(mCm.isActiveNetworkMetered());
// Connect VPN network.
- MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
+ TestNetworkAgentWrapper
+ vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
final ArraySet<UidRange> ranges = new ArraySet<>();
final int uid = Process.myUid();
ranges.add(new UidRange(uid, uid));
@@ -5582,21 +5339,21 @@
.build();
mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
- mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
+ mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
mCellNetworkAgent.connect(true);
cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
- mService.setUidRulesChanged(RULE_REJECT_ALL);
+ setUidRulesChanged(RULE_REJECT_ALL);
cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent);
// ConnectivityService should cache it not to invoke the callback again.
- mService.setUidRulesChanged(RULE_REJECT_METERED);
+ setUidRulesChanged(RULE_REJECT_METERED);
cellNetworkCallback.assertNoCallback();
- mService.setUidRulesChanged(RULE_NONE);
+ setUidRulesChanged(RULE_NONE);
cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
- mService.setUidRulesChanged(RULE_REJECT_METERED);
+ setUidRulesChanged(RULE_REJECT_METERED);
cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent);
// Restrict the network based on UID rule and NOT_METERED capability change.
@@ -5607,18 +5364,18 @@
cellNetworkCallback.expectCapabilitiesWithout(NET_CAPABILITY_NOT_METERED,
mCellNetworkAgent);
cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent);
- mService.setUidRulesChanged(RULE_ALLOW_METERED);
+ setUidRulesChanged(RULE_ALLOW_METERED);
cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
- mService.setUidRulesChanged(RULE_NONE);
+ setUidRulesChanged(RULE_NONE);
cellNetworkCallback.assertNoCallback();
// Restrict the network based on BackgroundRestricted.
- mService.setRestrictBackgroundChanged(true);
+ setRestrictBackgroundChanged(true);
cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent);
- mService.setRestrictBackgroundChanged(true);
+ setRestrictBackgroundChanged(true);
cellNetworkCallback.assertNoCallback();
- mService.setRestrictBackgroundChanged(false);
+ setRestrictBackgroundChanged(false);
cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
cellNetworkCallback.assertNoCallback();
@@ -5631,18 +5388,18 @@
mCm.registerDefaultNetworkCallback(defaultCallback);
// No Networkcallbacks invoked before any network is active.
- mService.setUidRulesChanged(RULE_REJECT_ALL);
- mService.setUidRulesChanged(RULE_NONE);
- mService.setUidRulesChanged(RULE_REJECT_METERED);
+ setUidRulesChanged(RULE_REJECT_ALL);
+ setUidRulesChanged(RULE_NONE);
+ setUidRulesChanged(RULE_REJECT_METERED);
defaultCallback.assertNoCallback();
- mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
+ mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
mCellNetworkAgent.connect(true);
defaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mCellNetworkAgent);
defaultCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mCellNetworkAgent);
// Allow to use the network after switching to NOT_METERED network.
- mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+ mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
mWiFiNetworkAgent.connect(true);
defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
@@ -5658,8 +5415,8 @@
defaultCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
// Verify there's no Networkcallbacks invoked after data saver on/off.
- mService.setRestrictBackgroundChanged(true);
- mService.setRestrictBackgroundChanged(false);
+ setRestrictBackgroundChanged(true);
+ setRestrictBackgroundChanged(false);
defaultCallback.assertNoCallback();
mCellNetworkAgent.disconnect();
@@ -5709,7 +5466,7 @@
mCm.registerNetworkCallback(networkRequest, networkCallback);
// Prepare ipv6 only link properties.
- mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
+ mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
final int cellNetId = mCellNetworkAgent.getNetwork().netId;
final LinkProperties cellLp = new LinkProperties();
cellLp.setInterfaceName(MOBILE_IFNAME);
@@ -5756,7 +5513,7 @@
verify(mMockDnsResolver, times(1)).startPrefix64Discovery(cellNetId);
// When NAT64 prefix discovery succeeds, LinkProperties are updated and clatd is started.
- Nat464Xlat clat = mService.getNat464Xlat(mCellNetworkAgent);
+ Nat464Xlat clat = getNat464Xlat(mCellNetworkAgent);
assertNull(mCm.getLinkProperties(mCellNetworkAgent.getNetwork()).getNat64Prefix());
mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, true /* added */,
kNat64PrefixString, 96);
@@ -5863,7 +5620,7 @@
.build();
mCm.registerNetworkCallback(networkRequest, networkCallback);
- mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
+ mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
final LinkProperties cellLp = new LinkProperties();
cellLp.setInterfaceName(MOBILE_IFNAME);
mCellNetworkAgent.sendLinkProperties(cellLp);
@@ -5873,7 +5630,7 @@
verify(mNetworkManagementService, times(1)).addIdleTimer(eq(MOBILE_IFNAME), anyInt(),
eq(ConnectivityManager.TYPE_MOBILE));
- mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+ mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
final LinkProperties wifiLp = new LinkProperties();
wifiLp.setInterfaceName(WIFI_IFNAME);
mWiFiNetworkAgent.sendLinkProperties(wifiLp);
@@ -5898,7 +5655,7 @@
eq(ConnectivityManager.TYPE_MOBILE));
// reconnect wifi
- mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+ mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
wifiLp.setInterfaceName(WIFI_IFNAME);
mWiFiNetworkAgent.sendLinkProperties(wifiLp);
mWiFiNetworkAgent.connect(true);
@@ -5944,7 +5701,7 @@
public void testTcpBufferReset() throws Exception {
final String testTcpBufferSizes = "1,2,3,4,5,6";
- mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
+ mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
reset(mMockNetd);
// Switching default network updates TCP buffer sizes.
mCellNetworkAgent.connect(false);
@@ -5960,7 +5717,7 @@
@Test
public void testGetGlobalProxyForNetwork() throws Exception {
final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
- mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+ mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
final Network wifiNetwork = mWiFiNetworkAgent.getNetwork();
when(mService.mProxyTracker.getGlobalProxy()).thenReturn(testProxyInfo);
assertEquals(testProxyInfo, mService.getProxyForNetwork(wifiNetwork));
@@ -5969,7 +5726,7 @@
@Test
public void testGetProxyForActiveNetwork() throws Exception {
final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
- mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+ mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
mWiFiNetworkAgent.connect(true);
waitForIdle();
assertNull(mService.getProxyForNetwork(null));
@@ -5988,14 +5745,15 @@
final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
// Set up a WiFi network with no proxy
- mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+ mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
mWiFiNetworkAgent.connect(true);
waitForIdle();
assertNull(mService.getProxyForNetwork(null));
// Set up a VPN network with a proxy
final int uid = Process.myUid();
- final MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
+ final TestNetworkAgentWrapper
+ vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
final ArraySet<UidRange> ranges = new ArraySet<>();
ranges.add(new UidRange(uid, uid));
mMockVpn.setUids(ranges);
@@ -6044,7 +5802,7 @@
lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
// The uid range needs to cover the test app so the network is visible to it.
final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(VPN_USER));
- final MockNetworkAgent vpnNetworkAgent = establishVpn(lp, VPN_UID, vpnRange);
+ final TestNetworkAgentWrapper vpnNetworkAgent = establishVpn(lp, VPN_UID, vpnRange);
// Connected VPN should have interface rules set up. There are two expected invocations,
// one during VPN uid update, one during VPN LinkProperties update
@@ -6070,7 +5828,8 @@
lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
// The uid range needs to cover the test app so the network is visible to it.
final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(VPN_USER));
- final MockNetworkAgent vpnNetworkAgent = establishVpn(lp, Process.SYSTEM_UID, vpnRange);
+ final TestNetworkAgentWrapper vpnNetworkAgent = establishVpn(
+ lp, Process.SYSTEM_UID, vpnRange);
// Legacy VPN should not have interface rules set up
verify(mMockNetd, never()).firewallAddUidInterfaceRules(any(), any());
@@ -6085,7 +5844,8 @@
lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), RTN_UNREACHABLE));
// The uid range needs to cover the test app so the network is visible to it.
final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(VPN_USER));
- final MockNetworkAgent vpnNetworkAgent = establishVpn(lp, Process.SYSTEM_UID, vpnRange);
+ final TestNetworkAgentWrapper vpnNetworkAgent = establishVpn(
+ lp, Process.SYSTEM_UID, vpnRange);
// IPv6 unreachable route should not be misinterpreted as a default route
verify(mMockNetd, never()).firewallAddUidInterfaceRules(any(), any());
@@ -6098,7 +5858,7 @@
lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
// The uid range needs to cover the test app so the network is visible to it.
final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(VPN_USER));
- final MockNetworkAgent vpnNetworkAgent = establishVpn(lp, VPN_UID, vpnRange);
+ final TestNetworkAgentWrapper vpnNetworkAgent = establishVpn(lp, VPN_UID, vpnRange);
// Connected VPN should have interface rules set up. There are two expected invocations,
// one during VPN uid update, one during VPN LinkProperties update
@@ -6147,7 +5907,7 @@
lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null));
// The uid range needs to cover the test app so the network is visible to it.
final UidRange vpnRange = UidRange.createForUser(VPN_USER);
- final MockNetworkAgent vpnNetworkAgent = establishVpn(lp, VPN_UID,
+ final TestNetworkAgentWrapper vpnNetworkAgent = establishVpn(lp, VPN_UID,
Collections.singleton(vpnRange));
reset(mMockNetd);
@@ -6169,9 +5929,10 @@
}
- private MockNetworkAgent establishVpn(LinkProperties lp, int establishingUid,
+ private TestNetworkAgentWrapper establishVpn(LinkProperties lp, int establishingUid,
Set<UidRange> vpnRange) throws Exception {
- final MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN, lp);
+ final TestNetworkAgentWrapper
+ vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN, lp);
vpnNetworkAgent.getNetworkCapabilities().setEstablishingVpnAppUid(establishingUid);
mMockVpn.setNetworkAgent(vpnNetworkAgent);
mMockVpn.connect();
diff --git a/tools/aapt2/optimize/ResourcePathShortener.cpp b/tools/aapt2/optimize/ResourcePathShortener.cpp
index 7f5d104..7ff9bf5 100644
--- a/tools/aapt2/optimize/ResourcePathShortener.cpp
+++ b/tools/aapt2/optimize/ResourcePathShortener.cpp
@@ -16,6 +16,7 @@
#include "optimize/ResourcePathShortener.h"
+#include <set>
#include <unordered_set>
#include "androidfw/StringPiece.h"
@@ -71,10 +72,19 @@
return shortened_path;
}
+// implement custom comparator of FileReference pointers so as to use the
+// underlying filepath as key rather than the integer address. This is to ensure
+// determinism of output for colliding files.
+struct PathComparator {
+ bool operator() (const FileReference* lhs, const FileReference* rhs) const {
+ return lhs->path->compare(*rhs->path);
+ }
+};
+
bool ResourcePathShortener::Consume(IAaptContext* context, ResourceTable* table) {
// used to detect collisions
std::unordered_set<std::string> shortened_paths;
- std::unordered_set<FileReference*> file_refs;
+ std::set<FileReference*, PathComparator> file_refs;
for (auto& package : table->packages) {
for (auto& type : package->types) {
for (auto& entry : type->entries) {
diff --git a/tools/aapt2/optimize/ResourcePathShortener_test.cpp b/tools/aapt2/optimize/ResourcePathShortener_test.cpp
index 1f45694..f5a02be 100644
--- a/tools/aapt2/optimize/ResourcePathShortener_test.cpp
+++ b/tools/aapt2/optimize/ResourcePathShortener_test.cpp
@@ -29,6 +29,14 @@
return android::StringPiece(iter, path.end() - iter);
}
+void FillTable(aapt::test::ResourceTableBuilder& builder, int start, int end) {
+ for (int i=start; i<end; i++) {
+ builder.AddFileReference(
+ "android:drawable/xmlfile" + std::to_string(i),
+ "res/drawable/xmlfile" + std::to_string(i) + ".xml");
+ }
+}
+
namespace aapt {
TEST(ResourcePathShortenerTest, FileRefPathsChangedInResourceTable) {
@@ -114,4 +122,45 @@
EXPECT_THAT(GetExtension(path_map[original_png_path]), Eq(android::StringPiece(".png")));
}
+TEST(ResourcePathShortenerTest, DeterministicallyHandleCollisions) {
+ std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
+
+ // 4000 resources is the limit at which the hash space is expanded to 3
+ // letters to reduce collisions, we want as many collisions as possible thus
+ // N-1.
+ const auto kNumResources = 3999;
+ const auto kNumTries = 5;
+
+ test::ResourceTableBuilder builder1;
+ FillTable(builder1, 0, kNumResources);
+ std::unique_ptr<ResourceTable> table1 = builder1.Build();
+ std::map<std::string, std::string> expected_mapping;
+ ASSERT_TRUE(ResourcePathShortener(expected_mapping).Consume(context.get(), table1.get()));
+
+ // We are trying to ensure lack of non-determinism, it is not simple to prove
+ // a negative, thus we must try the test a few times so that the test itself
+ // is non-flaky. Basically create the pathmap 5 times from the same set of
+ // resources but a different order of addition and then ensure they are always
+ // mapped to the same short path.
+ for (int i=0; i<kNumTries; i++) {
+ test::ResourceTableBuilder builder2;
+ // This loop adds resources to the resource table in the range of
+ // [0:kNumResources). Adding the file references in different order makes
+ // non-determinism more likely to surface. Thus we add resources
+ // [start_index:kNumResources) first then [0:start_index). We also use a
+ // different start_index each run.
+ int start_index = (kNumResources/kNumTries)*i;
+ FillTable(builder2, start_index, kNumResources);
+ FillTable(builder2, 0, start_index);
+ std::unique_ptr<ResourceTable> table2 = builder2.Build();
+
+ std::map<std::string, std::string> actual_mapping;
+ ASSERT_TRUE(ResourcePathShortener(actual_mapping).Consume(context.get(), table2.get()));
+
+ for (auto& item : actual_mapping) {
+ ASSERT_THAT(expected_mapping[item.first], Eq(item.second));
+ }
+ }
+}
+
} // namespace aapt
diff --git a/tools/codegen/src/com/android/codegen/ClassInfo.kt b/tools/codegen/src/com/android/codegen/ClassInfo.kt
index 578fb28..5061be2 100644
--- a/tools/codegen/src/com/android/codegen/ClassInfo.kt
+++ b/tools/codegen/src/com/android/codegen/ClassInfo.kt
@@ -1,22 +1,37 @@
package com.android.codegen
-import com.github.javaparser.JavaParser
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>) {
private val userSourceCode = (sourceLines + "}").joinToString("\n")
- val fileAst = try {
- JavaParser.parse(userSourceCode)!!
+ val fileAst: CompilationUnit = try {
+ JAVA_PARSER.parse(userSourceCode).throwIfFailed()
} catch (e: ParseProblemException) {
- throw RuntimeException("Failed to parse code:\n" +
+ throw parseFailed(cause = e)
+ }
+
+ 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"),
- e)
+ .joinToString("\n") + "\n$desc",
+ cause)
}
+
val classAst = fileAst.types[0] as ClassOrInterfaceDeclaration
val nestedClasses = classAst.members.filterIsInstance<ClassOrInterfaceDeclaration>()
diff --git a/tools/codegen/src/com/android/codegen/ClassPrinter.kt b/tools/codegen/src/com/android/codegen/ClassPrinter.kt
index f1645ea..1f0d4b8 100644
--- a/tools/codegen/src/com/android/codegen/ClassPrinter.kt
+++ b/tools/codegen/src/com/android/codegen/ClassPrinter.kt
@@ -42,7 +42,7 @@
init {
val fieldsWithMissingNullablity = fields.filter { field ->
!field.isPrimitive
- && Modifier.TRANSIENT !in field.fieldAst.modifiers
+ && field.fieldAst.modifiers.none { it.keyword == Modifier.Keyword.TRANSIENT }
&& "@$Nullable" !in field.annotations
&& "@$NonNull" !in field.annotations
}
@@ -122,9 +122,13 @@
if (cliArgs.contains("--$kebabCase")) return true
val annotationKey = "gen$upperCamelCase"
+ val annotationHiddenKey = "genHidden$upperCamelCase"
if (dataClassAnnotationFeatures.containsKey(annotationKey)) {
return dataClassAnnotationFeatures[annotationKey]!!
}
+ if (dataClassAnnotationFeatures.containsKey(annotationHiddenKey)) {
+ return dataClassAnnotationFeatures[annotationHiddenKey]!!
+ }
if (cliArgs.contains("--all")) return true
if (hidden) return true
@@ -144,11 +148,17 @@
}
}
- val FeatureFlag.hidden
- get(): Boolean = when {
- cliArgs.contains("--hidden-$kebabCase") -> true
- this == FeatureFlag.BUILD_UPON -> FeatureFlag.BUILDER.hidden
- else -> false
+ val FeatureFlag.hidden: Boolean
+ get(): Boolean {
+ val annotationHiddenKey = "genHidden$upperCamelCase"
+ if (dataClassAnnotationFeatures.containsKey(annotationHiddenKey)) {
+ return dataClassAnnotationFeatures[annotationHiddenKey]!!
+ }
+ return when {
+ cliArgs.contains("--hidden-$kebabCase") -> true
+ this == FeatureFlag.BUILD_UPON -> FeatureFlag.BUILDER.hidden
+ else -> false
+ }
}
var currentIndent = INDENT_SINGLE
diff --git a/tools/codegen/src/com/android/codegen/FieldInfo.kt b/tools/codegen/src/com/android/codegen/FieldInfo.kt
index 74e7948..ba00264 100644
--- a/tools/codegen/src/com/android/codegen/FieldInfo.kt
+++ b/tools/codegen/src/com/android/codegen/FieldInfo.kt
@@ -1,6 +1,5 @@
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
@@ -85,7 +84,6 @@
classInfo.classAst.methods.find {
it.nameAsString == "default$NameUpperCamel" && it.parameters.isEmpty()
}?.run { return "$nameAsString()" }
- if (FieldClass == "List") return "${classPrinter.memberRef("java.util.Collections.emptyList")}()"
return null
}
val hasDefault get() = defaultExpr != null
@@ -115,8 +113,9 @@
classPrinter {
fieldAst.addAnnotation(SingleMemberAnnotationExpr(
Name(ParcelWith),
- ClassExpr(JavaParser.parseClassOrInterfaceType(
- "$Parcelling.BuiltIn.For$FieldClass"))))
+ ClassExpr(JAVA_PARSER
+ .parseClassOrInterfaceType("$Parcelling.BuiltIn.For$FieldClass")
+ .throwIfFailed())))
}
}
fieldAst.annotations.map { it.removeComment().toString() }
diff --git a/tools/codegen/src/com/android/codegen/Generators.kt b/tools/codegen/src/com/android/codegen/Generators.kt
index c6e0a06..914e475 100644
--- a/tools/codegen/src/com/android/codegen/Generators.kt
+++ b/tools/codegen/src/com/android/codegen/Generators.kt
@@ -68,12 +68,15 @@
}
}
- val visibility = if (consts[0].second.isPublic) "public" else "/* package-*/"
+ val visibility = if (consts[0].second.isPublic) "public" else "/* package-private */"
val Retention = classRef("java.lang.annotation.Retention")
val RetentionPolicySource = memberRef("java.lang.annotation.RetentionPolicy.SOURCE")
val ConstDef = classRef("android.annotation.${type.capitalize()}Def")
+ if (FeatureFlag.CONST_DEFS.hidden) {
+ +"/** @hide */"
+ }
"@$ConstDef(${if_(flag, "flag = true, ")}prefix = \"${prefix}_\", value = {" {
names.forEachLastAware { name, isLast ->
+"$name${if_(!isLast, ",")}"
@@ -85,6 +88,9 @@
+""
if (type == "int") {
+ if (FeatureFlag.CONST_DEFS.hidden) {
+ +"/** @hide */"
+ }
+GENERATED_MEMBER_HEADER
val methodDefLine = "$visibility static String ${AnnotationName.decapitalize()}ToString(" +
"@$AnnotationName int value)"
diff --git a/tools/codegen/src/com/android/codegen/InputSignaturesComputation.kt b/tools/codegen/src/com/android/codegen/InputSignaturesComputation.kt
index 1e7a267..24cf469 100644
--- a/tools/codegen/src/com/android/codegen/InputSignaturesComputation.kt
+++ b/tools/codegen/src/com/android/codegen/InputSignaturesComputation.kt
@@ -18,7 +18,7 @@
return classAst.fields.map { fieldAst ->
buildString {
- append(fieldAst.modifiers.joinToString(" ") { it.asString() })
+ append(fieldAst.modifiers.joinToString(" ") { it.keyword.asString() })
append(" ")
append(annotationsToString(fieldAst))
append(" ")
@@ -28,7 +28,7 @@
}
} + classAst.methods.map { methodAst ->
buildString {
- append(methodAst.modifiers.joinToString(" ") { it.asString() })
+ append(methodAst.modifiers.joinToString(" ") { it.keyword.asString() })
append(" ")
append(annotationsToString(methodAst))
append(" ")
@@ -97,7 +97,7 @@
getFullClassName(buildString {
type.scope.ifPresent { append(it).append(".") }
append(type.nameAsString)
- }) + (type.typeArguments.orElse(null)?.let { args -> args.joinToString(", ") {getFullClassName(it)}}?.let { "<$it>" } ?: "")
+ }) + (type.typeArguments.orElse(null)?.let { args -> args.joinToString(",") {getFullClassName(it)}}?.let { "<$it>" } ?: "")
} else getFullClassName(type.asString())
}
diff --git a/tools/codegen/src/com/android/codegen/Main.kt b/tools/codegen/src/com/android/codegen/Main.kt
index f71bfd3..0f932f3 100755
--- a/tools/codegen/src/com/android/codegen/Main.kt
+++ b/tools/codegen/src/com/android/codegen/Main.kt
@@ -1,5 +1,6 @@
package com.android.codegen
+import com.github.javaparser.JavaParser
import java.io.File
@@ -14,6 +15,7 @@
const val FLAG_BUILDER_PROTECTED_SETTERS = "--builder-protected-setters"
const val FLAG_NO_FULL_QUALIFIERS = "--no-full-qualifiers"
+val JAVA_PARSER = JavaParser()
/** @see [FeatureFlag] */
val USAGE = """
diff --git a/tools/codegen/src/com/android/codegen/Utils.kt b/tools/codegen/src/com/android/codegen/Utils.kt
index 73ceac4..a1f068a 100644
--- a/tools/codegen/src/com/android/codegen/Utils.kt
+++ b/tools/codegen/src/com/android/codegen/Utils.kt
@@ -79,7 +79,7 @@
.withZone(ZoneId.systemDefault())
.format(Instant.now())
-val NodeWithModifiers<*>.visibility get() = Modifier.getAccessSpecifier(modifiers)
+val NodeWithModifiers<*>.visibility get() = accessSpecifier
fun abort(msg: String): Nothing {
System.err.println("ERROR: $msg")
@@ -88,4 +88,3 @@
}
fun bitAtExpr(bitIndex: Int) = "0x${java.lang.Long.toHexString(1L shl bitIndex)}"
-
diff --git a/tools/processors/staledataclass/src/android/processor/staledataclass/StaleDataclassProcessor.kt b/tools/processors/staledataclass/src/android/processor/staledataclass/StaleDataclassProcessor.kt
index 26b15ae..d00def6 100644
--- a/tools/processors/staledataclass/src/android/processor/staledataclass/StaleDataclassProcessor.kt
+++ b/tools/processors/staledataclass/src/android/processor/staledataclass/StaleDataclassProcessor.kt
@@ -66,10 +66,14 @@
if (dataClassAnnotation == null) {
dataClassAnnotation = annotations.find {
it.qualifiedName.toString() == DATACLASS_ANNOTATION_NAME
- }
+ } ?: return true
}
- val generatedAnnotatedElements = roundEnv.getElementsAnnotatedWith(generatedAnnotation)
+ val generatedAnnotatedElements = if (generatedAnnotation != null) {
+ roundEnv.getElementsAnnotatedWith(generatedAnnotation)
+ } else {
+ emptySet()
+ }
generatedAnnotatedElements.forEach {
processSingleFile(it)
}