Merge "Rearrange listener logic so it can be overriden"
diff --git a/Android.bp b/Android.bp
index ea14b9d..a082085 100644
--- a/Android.bp
+++ b/Android.bp
@@ -212,6 +212,7 @@
name: "framework-non-updatable-sources",
srcs: [
// Java/AIDL sources under frameworks/base
+ ":framework-appsearch-sources",
":framework-blobstore-sources",
":framework-core-sources",
":framework-drm-sources",
@@ -870,11 +871,13 @@
srcs: [
"core/java/android/os/HidlSupport.java",
"core/java/android/annotation/IntDef.java",
+ "core/java/android/annotation/IntRange.java",
"core/java/android/annotation/NonNull.java",
"core/java/android/annotation/Nullable.java",
"core/java/android/annotation/SystemApi.java",
"core/java/android/annotation/TestApi.java",
"core/java/android/annotation/UnsupportedAppUsage.java",
+ "core/java/android/os/HidlMemory.java",
"core/java/android/os/HwBinder.java",
"core/java/android/os/HwBlob.java",
"core/java/android/os/HwParcel.java",
@@ -1083,6 +1086,7 @@
":core-current-stubs-source",
":core_public_api_files",
":updatable-media-srcs",
+ ":ike-api-srcs",
],
libs: ["framework-internal-utils"],
installable: false,
@@ -1405,8 +1409,10 @@
srcs: [
"core/java/android/os/HidlSupport.java",
"core/java/android/annotation/IntDef.java",
+ "core/java/android/annotation/IntRange.java",
"core/java/android/annotation/NonNull.java",
"core/java/android/annotation/SystemApi.java",
+ "core/java/android/os/HidlMemory.java",
"core/java/android/os/HwBinder.java",
"core/java/android/os/HwBlob.java",
"core/java/android/os/HwParcel.java",
diff --git a/CleanSpec.mk b/CleanSpec.mk
index f7a2858..8fac394 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -255,6 +255,7 @@
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/app/CaptivePortalLogin)
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/framework/ext.jar)
$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/telephony/java/com/google/android/mms)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/framework/*-service.jar)
# ******************************************************************
# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST ABOVE THIS BANNER
# ******************************************************************
diff --git a/apex/appsearch/framework/Android.bp b/apex/appsearch/framework/Android.bp
new file mode 100644
index 0000000..0a65f73
--- /dev/null
+++ b/apex/appsearch/framework/Android.bp
@@ -0,0 +1,39 @@
+// 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.
+
+filegroup {
+ name: "framework-appsearch-sources",
+ srcs: [
+ "java/**/*.java",
+ "java/**/*.aidl",
+ ],
+ path: "java",
+}
+
+java_library {
+ name: "framework-appsearch",
+ installable: false,
+ sdk_version: "core_platform",
+ srcs: [
+ ":framework-appsearch-sources",
+ ],
+ aidl: {
+ export_include_dirs: [
+ "java",
+ ],
+ },
+ libs: [
+ "framework-minus-apex",
+ ],
+}
diff --git a/apex/appsearch/framework/java/android/app/appsearch/AppSearchManager.java b/apex/appsearch/framework/java/android/app/appsearch/AppSearchManager.java
new file mode 100644
index 0000000..a8ee35c
--- /dev/null
+++ b/apex/appsearch/framework/java/android/app/appsearch/AppSearchManager.java
@@ -0,0 +1,35 @@
+/*
+ * 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.appsearch;
+
+import android.annotation.SystemService;
+import android.content.Context;
+
+/**
+ * TODO(b/142567528): add comments when implement this class
+ * @hide
+ */
+@SystemService(Context.APP_SEARCH_SERVICE)
+public class AppSearchManager {
+ private final IAppSearchManager mService;
+ /**
+ * TODO(b/142567528): add comments when implement this class
+ * @hide
+ */
+ public AppSearchManager(IAppSearchManager service) {
+ mService = service;
+ }
+}
diff --git a/apex/appsearch/framework/java/android/app/appsearch/AppSearchManagerFrameworkInitializer.java b/apex/appsearch/framework/java/android/app/appsearch/AppSearchManagerFrameworkInitializer.java
new file mode 100644
index 0000000..fcebe3d
--- /dev/null
+++ b/apex/appsearch/framework/java/android/app/appsearch/AppSearchManagerFrameworkInitializer.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.app.appsearch;
+
+import android.app.SystemServiceRegistry;
+import android.content.Context;
+
+/**
+ * This is where the AppSearchManagerService wrapper is registered.
+ *
+ * TODO(b/142567528): add comments when implement this class
+ * @hide
+ */
+public class AppSearchManagerFrameworkInitializer {
+
+ /**
+ * TODO(b/142567528): add comments when implement this class
+ */
+ public static void initialize() {
+ SystemServiceRegistry.registerStaticService(
+ Context.APP_SEARCH_SERVICE, AppSearchManager.class,
+ (service) -> new AppSearchManager(IAppSearchManager.Stub.asInterface(service)));
+ }
+}
diff --git a/apex/appsearch/framework/java/android/app/appsearch/IAppSearchManager.aidl b/apex/appsearch/framework/java/android/app/appsearch/IAppSearchManager.aidl
new file mode 100644
index 0000000..f0f4f51
--- /dev/null
+++ b/apex/appsearch/framework/java/android/app/appsearch/IAppSearchManager.aidl
@@ -0,0 +1,19 @@
+/**
+ * Copyright 2019, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.app.appsearch;
+/** {@hide} */
+interface IAppSearchManager {
+}
diff --git a/apex/appsearch/service/Android.bp b/apex/appsearch/service/Android.bp
new file mode 100644
index 0000000..2cd7aa0
--- /dev/null
+++ b/apex/appsearch/service/Android.bp
@@ -0,0 +1,24 @@
+// 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.
+java_library {
+ name: "service-appsearch",
+ installable: true,
+ srcs: [
+ "java/**/*.java",
+ ],
+ libs: [
+ "framework",
+ "services.core",
+ ],
+}
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java b/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java
new file mode 100644
index 0000000..4d44d9d
--- /dev/null
+++ b/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java
@@ -0,0 +1,39 @@
+/*
+ * 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.appsearch;
+
+import android.app.appsearch.IAppSearchManager;
+import android.content.Context;
+
+import com.android.server.SystemService;
+
+/**
+ * TODO(b/142567528): add comments when implement this class
+ */
+public class AppSearchManagerService extends SystemService {
+
+ public AppSearchManagerService(Context context) {
+ super(context);
+ }
+
+ @Override
+ public void onStart() {
+ publishBinderService(Context.APP_SEARCH_SERVICE, new Stub());
+ }
+
+ private class Stub extends IAppSearchManager.Stub {
+ }
+}
diff --git a/apex/blobstore/service/Android.bp b/apex/blobstore/service/Android.bp
index 019f989..d8caa5a 100644
--- a/apex/blobstore/service/Android.bp
+++ b/apex/blobstore/service/Android.bp
@@ -13,7 +13,7 @@
// limitations under the License.
java_library {
- name: "blobstore-service",
+ name: "service-blobstore",
installable: true,
srcs: [
@@ -24,4 +24,4 @@
"framework",
"services.core",
],
-}
\ No newline at end of file
+}
diff --git a/apex/jobscheduler/README_js-mainline.md b/apex/jobscheduler/README_js-mainline.md
index ea20e3e..134ff3d 100644
--- a/apex/jobscheduler/README_js-mainline.md
+++ b/apex/jobscheduler/README_js-mainline.md
@@ -2,14 +2,14 @@
## Current structure
-- JS service side classes are put in `jobscheduler-service.jar`.
+- JS service side classes are put in `service-jobscheduler.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/ethernet-service.jar:/system/framework/com.android.location.provider.jar:/system/framework/jobscheduler-service.jar`
+`SYSTEMSERVERCLASSPATH=/system/framework/services.jar:/system/framework/ethernet-service.jar:/system/framework/com.android.location.provider.jar:/system/framework/service-jobscheduler.jar`
`SYSTEMSERVERCLASSPATH` is generated from `PRODUCT_SYSTEM_SERVER_JARS`.
-- JS framework side classes are put in `jobscheduler-framework.jar`,
+- JS framework side classes are put in `framework-jobscheduler.jar`,
and the rest of the framework code is put in `framework-minus-apex.jar`,
as of http://ag/9145619.
diff --git a/apex/jobscheduler/framework/Android.bp b/apex/jobscheduler/framework/Android.bp
index 3902aa2..98bbe82 100644
--- a/apex/jobscheduler/framework/Android.bp
+++ b/apex/jobscheduler/framework/Android.bp
@@ -11,7 +11,7 @@
}
java_library {
- name: "jobscheduler-framework",
+ name: "framework-jobscheduler",
installable: false,
compile_dex: true,
sdk_version: "core_platform",
diff --git a/apex/jobscheduler/framework/java/android/app/job/JobSchedulerFrameworkInitializer.java b/apex/jobscheduler/framework/java/android/app/job/JobSchedulerFrameworkInitializer.java
index f3ec5e5..3835d93 100644
--- a/apex/jobscheduler/framework/java/android/app/job/JobSchedulerFrameworkInitializer.java
+++ b/apex/jobscheduler/framework/java/android/app/job/JobSchedulerFrameworkInitializer.java
@@ -21,6 +21,7 @@
import android.content.Context;
import android.os.DeviceIdleManager;
import android.os.IDeviceIdleController;
+import android.os.PowerWhitelistManager;
/**
* Class holding initialization code for the job scheduler module.
@@ -48,5 +49,8 @@
Context.DEVICE_IDLE_CONTROLLER, DeviceIdleManager.class,
(context, b) -> new DeviceIdleManager(
context, IDeviceIdleController.Stub.asInterface(b)));
+ SystemServiceRegistry.registerContextAwareService(
+ Context.POWER_WHITELIST_MANAGER, PowerWhitelistManager.class,
+ PowerWhitelistManager::new);
}
}
diff --git a/apex/jobscheduler/framework/java/android/os/PowerWhitelistManager.java b/apex/jobscheduler/framework/java/android/os/PowerWhitelistManager.java
new file mode 100644
index 0000000..06ed52d
--- /dev/null
+++ b/apex/jobscheduler/framework/java/android/os/PowerWhitelistManager.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os;
+
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
+import android.annotation.SystemService;
+import android.annotation.TestApi;
+import android.content.Context;
+
+/**
+ * Interface to access and modify the power save whitelist.
+ *
+ * @hide
+ */
+@SystemApi
+@TestApi
+@SystemService(Context.POWER_WHITELIST_MANAGER)
+public class PowerWhitelistManager {
+ private final Context mContext;
+
+ /**
+ * @hide
+ */
+ public PowerWhitelistManager(@NonNull Context context) {
+ mContext = context;
+ }
+}
diff --git a/apex/jobscheduler/service/Android.bp b/apex/jobscheduler/service/Android.bp
index ca6dc45..c9d9d6c 100644
--- a/apex/jobscheduler/service/Android.bp
+++ b/apex/jobscheduler/service/Android.bp
@@ -1,7 +1,7 @@
// Job Scheduler Service jar, which will eventually be put in the jobscheduler mainline apex.
-// jobscheduler-service needs to be added to PRODUCT_SYSTEM_SERVER_JARS.
+// service-jobscheduler needs to be added to PRODUCT_SYSTEM_SERVER_JARS.
java_library {
- name: "jobscheduler-service",
+ name: "service-jobscheduler",
installable: true,
srcs: [
diff --git a/apex/statsd/service/Android.bp b/apex/statsd/service/Android.bp
index 786e8b0..f71d74f 100644
--- a/apex/statsd/service/Android.bp
+++ b/apex/statsd/service/Android.bp
@@ -1,8 +1,8 @@
// Statsd Service jar, which will eventually be put in the statsd mainline apex.
-// statsd-service needs to be added to PRODUCT_SYSTEM_SERVER_JARS.
+// service-statsd needs to be added to PRODUCT_SYSTEM_SERVER_JARS.
// This jar will contain StatsCompanionService
java_library {
- name: "statsd-service",
+ name: "service-statsd",
installable: true,
srcs: [
@@ -13,4 +13,4 @@
"framework",
"services.core",
],
-}
\ No newline at end of file
+}
diff --git a/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java b/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java
index 8a00c83..a6cc06f 100644
--- a/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java
+++ b/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java
@@ -2076,6 +2076,7 @@
private void pullDangerousPermissionState(long elapsedNanos, final long wallClockNanos,
List<StatsLogEventWrapper> pulledData) {
long token = Binder.clearCallingIdentity();
+ Set<Integer> reportedUids = new HashSet<>();
try {
PackageManager pm = mContext.getPackageManager();
@@ -2096,6 +2097,12 @@
continue;
}
+ if (reportedUids.contains(pkg.applicationInfo.uid)) {
+ // do not report same uid twice
+ continue;
+ }
+ reportedUids.add(pkg.applicationInfo.uid);
+
int numPerms = pkg.requestedPermissions.length;
for (int permNum = 0; permNum < numPerms; permNum++) {
String permName = pkg.requestedPermissions[permNum];
@@ -2120,7 +2127,7 @@
e.writeString(permName);
e.writeInt(pkg.applicationInfo.uid);
- e.writeString(pkg.packageName);
+ e.writeString(null);
e.writeBoolean((pkg.requestedPermissionsFlags[permNum]
& REQUESTED_PERMISSION_GRANTED) != 0);
e.writeInt(permissionFlags);
diff --git a/api/current.txt b/api/current.txt
index 1728c53..c2939fd 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -2955,7 +2955,6 @@
field public static final int FEEDBACK_SPOKEN = 1; // 0x1
field public static final int FEEDBACK_VISUAL = 8; // 0x8
field public static final int FLAG_ENABLE_ACCESSIBILITY_VOLUME = 128; // 0x80
- field public static final int FLAG_HANDLE_SHORTCUT = 2048; // 0x800
field public static final int FLAG_INCLUDE_NOT_IMPORTANT_VIEWS = 2; // 0x2
field public static final int FLAG_REPORT_VIEW_IDS = 16; // 0x10
field public static final int FLAG_REQUEST_ACCESSIBILITY_BUTTON = 256; // 0x100
@@ -4760,18 +4759,18 @@
field public static final int VISIBILITY_VISIBLE_NOTIFY_ONLY_COMPLETION = 3; // 0x3
}
- public class ExpandableListActivity extends android.app.Activity implements android.widget.ExpandableListView.OnChildClickListener android.widget.ExpandableListView.OnGroupCollapseListener android.widget.ExpandableListView.OnGroupExpandListener android.view.View.OnCreateContextMenuListener {
- ctor public ExpandableListActivity();
- method public android.widget.ExpandableListAdapter getExpandableListAdapter();
- method public android.widget.ExpandableListView getExpandableListView();
- method public long getSelectedId();
- method public long getSelectedPosition();
- method public boolean onChildClick(android.widget.ExpandableListView, android.view.View, int, int, long);
- method public void onGroupCollapse(int);
- method public void onGroupExpand(int);
- method public void setListAdapter(android.widget.ExpandableListAdapter);
- method public boolean setSelectedChild(int, int, boolean);
- method public void setSelectedGroup(int);
+ @Deprecated public class ExpandableListActivity extends android.app.Activity implements android.widget.ExpandableListView.OnChildClickListener android.widget.ExpandableListView.OnGroupCollapseListener android.widget.ExpandableListView.OnGroupExpandListener android.view.View.OnCreateContextMenuListener {
+ ctor @Deprecated public ExpandableListActivity();
+ method @Deprecated public android.widget.ExpandableListAdapter getExpandableListAdapter();
+ method @Deprecated public android.widget.ExpandableListView getExpandableListView();
+ method @Deprecated public long getSelectedId();
+ method @Deprecated public long getSelectedPosition();
+ method @Deprecated public boolean onChildClick(android.widget.ExpandableListView, android.view.View, int, int, long);
+ method @Deprecated public void onGroupCollapse(int);
+ method @Deprecated public void onGroupExpand(int);
+ method @Deprecated public void setListAdapter(android.widget.ExpandableListAdapter);
+ method @Deprecated public boolean setSelectedChild(int, int, boolean);
+ method @Deprecated public void setSelectedGroup(int);
}
@Deprecated public class Fragment implements android.content.ComponentCallbacks2 android.view.View.OnCreateContextMenuListener {
@@ -5213,40 +5212,40 @@
method @Deprecated public void onKeyguardExitResult(boolean);
}
- public abstract class LauncherActivity extends android.app.ListActivity {
- ctor public LauncherActivity();
- method protected android.content.Intent getTargetIntent();
- method protected android.content.Intent intentForPosition(int);
- method protected android.app.LauncherActivity.ListItem itemForPosition(int);
- method public java.util.List<android.app.LauncherActivity.ListItem> makeListItems();
- method protected java.util.List<android.content.pm.ResolveInfo> onQueryPackageManager(android.content.Intent);
- method protected void onSetContentView();
+ @Deprecated public abstract class LauncherActivity extends android.app.ListActivity {
+ ctor @Deprecated public LauncherActivity();
+ method @Deprecated protected android.content.Intent getTargetIntent();
+ method @Deprecated protected android.content.Intent intentForPosition(int);
+ method @Deprecated protected android.app.LauncherActivity.ListItem itemForPosition(int);
+ method @Deprecated public java.util.List<android.app.LauncherActivity.ListItem> makeListItems();
+ method @Deprecated protected java.util.List<android.content.pm.ResolveInfo> onQueryPackageManager(android.content.Intent);
+ method @Deprecated protected void onSetContentView();
}
- public class LauncherActivity.IconResizer {
- ctor public LauncherActivity.IconResizer();
- method public android.graphics.drawable.Drawable createIconThumbnail(android.graphics.drawable.Drawable);
+ @Deprecated public class LauncherActivity.IconResizer {
+ ctor @Deprecated public LauncherActivity.IconResizer();
+ method @Deprecated public android.graphics.drawable.Drawable createIconThumbnail(android.graphics.drawable.Drawable);
}
- public static class LauncherActivity.ListItem {
- ctor public LauncherActivity.ListItem();
- field public String className;
- field public android.os.Bundle extras;
- field public android.graphics.drawable.Drawable icon;
- field public CharSequence label;
- field public String packageName;
- field public android.content.pm.ResolveInfo resolveInfo;
+ @Deprecated public static class LauncherActivity.ListItem {
+ ctor @Deprecated public LauncherActivity.ListItem();
+ field @Deprecated public String className;
+ field @Deprecated public android.os.Bundle extras;
+ field @Deprecated public android.graphics.drawable.Drawable icon;
+ field @Deprecated public CharSequence label;
+ field @Deprecated public String packageName;
+ field @Deprecated public android.content.pm.ResolveInfo resolveInfo;
}
- public class ListActivity extends android.app.Activity {
- ctor public ListActivity();
- method public android.widget.ListAdapter getListAdapter();
- method public android.widget.ListView getListView();
- method public long getSelectedItemId();
- method public int getSelectedItemPosition();
- method protected void onListItemClick(android.widget.ListView, android.view.View, int, long);
- method public void setListAdapter(android.widget.ListAdapter);
- method public void setSelection(int);
+ @Deprecated public class ListActivity extends android.app.Activity {
+ ctor @Deprecated public ListActivity();
+ method @Deprecated public android.widget.ListAdapter getListAdapter();
+ method @Deprecated public android.widget.ListView getListView();
+ method @Deprecated public long getSelectedItemId();
+ method @Deprecated public int getSelectedItemPosition();
+ method @Deprecated protected void onListItemClick(android.widget.ListView, android.view.View, int, long);
+ method @Deprecated public void setListAdapter(android.widget.ListAdapter);
+ method @Deprecated public void setSelection(int);
}
@Deprecated public class ListFragment extends android.app.Fragment {
@@ -5616,6 +5615,7 @@
method @Deprecated public android.app.Notification.Builder setDefaults(int);
method @NonNull public android.app.Notification.Builder setDeleteIntent(android.app.PendingIntent);
method @NonNull public android.app.Notification.Builder setExtras(android.os.Bundle);
+ method @NonNull public android.app.Notification.Builder setFlag(int, boolean);
method @NonNull public android.app.Notification.Builder setFullScreenIntent(android.app.PendingIntent, boolean);
method @NonNull public android.app.Notification.Builder setGroup(String);
method @NonNull public android.app.Notification.Builder setGroupAlertBehavior(int);
@@ -9927,6 +9927,7 @@
field public static final String ALARM_SERVICE = "alarm";
field public static final String APPWIDGET_SERVICE = "appwidget";
field public static final String APP_OPS_SERVICE = "appops";
+ field public static final String APP_SEARCH_SERVICE = "app_search";
field public static final String AUDIO_SERVICE = "audio";
field public static final String BATTERY_SERVICE = "batterymanager";
field public static final int BIND_ABOVE_CLIENT = 8; // 0x8
@@ -29164,14 +29165,17 @@
}
public class ProxyInfo implements android.os.Parcelable {
+ ctor public ProxyInfo(@Nullable android.net.ProxyInfo);
method public static android.net.ProxyInfo buildDirectProxy(String, int);
method public static android.net.ProxyInfo buildDirectProxy(String, int, java.util.List<java.lang.String>);
method public static android.net.ProxyInfo buildPacProxy(android.net.Uri);
+ method @NonNull public static android.net.ProxyInfo buildPacProxy(@NonNull android.net.Uri, int);
method public int describeContents();
method public String[] getExclusionList();
method public String getHost();
method public android.net.Uri getPacFileUrl();
method public int getPort();
+ method public boolean isValid();
method public void writeToParcel(android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.net.ProxyInfo> CREATOR;
}
@@ -30060,7 +30064,8 @@
method public void addOrUpdatePasspointConfiguration(android.net.wifi.hotspot2.PasspointConfiguration);
method @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) public void addScanResultsListener(@NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.WifiManager.ScanResultsListener);
method @RequiresPermission(allOf={android.Manifest.permission.ACCESS_FINE_LOCATION, android.Manifest.permission.ACCESS_WIFI_STATE}) public void addSuggestionConnectionStatusListener(@NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.WifiManager.SuggestionConnectionStatusListener);
- method public static int calculateSignalLevel(int, int);
+ method @Deprecated public static int calculateSignalLevel(int, int);
+ method public int calculateSignalLevel(int);
method @Deprecated public void cancelWps(android.net.wifi.WifiManager.WpsCallback);
method public static int compareSignalLevel(int, int);
method public android.net.wifi.WifiManager.MulticastLock createMulticastLock(String);
@@ -30073,6 +30078,7 @@
method public android.net.wifi.WifiInfo getConnectionInfo();
method public android.net.DhcpInfo getDhcpInfo();
method public int getMaxNumberOfNetworkSuggestionsPerApp();
+ method public int getMaxSignalLevel();
method @NonNull @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) public java.util.List<android.net.wifi.WifiNetworkSuggestion> getNetworkSuggestions();
method @Deprecated @RequiresPermission(anyOf={"android.permission.NETWORK_SETTINGS", "android.permission.NETWORK_SETUP_WIZARD"}) public java.util.List<android.net.wifi.hotspot2.PasspointConfiguration> getPasspointConfigurations();
method public java.util.List<android.net.wifi.ScanResult> getScanResults();
@@ -34823,8 +34829,8 @@
}
public final class FileUtils {
- method public static void closeQuietly(@Nullable AutoCloseable);
- method public static void closeQuietly(@Nullable java.io.FileDescriptor);
+ method @Deprecated public static void closeQuietly(@Nullable AutoCloseable);
+ method @Deprecated public static void closeQuietly(@Nullable java.io.FileDescriptor);
method public static long copy(@NonNull java.io.InputStream, @NonNull java.io.OutputStream) throws java.io.IOException;
method public static long copy(@NonNull java.io.InputStream, @NonNull java.io.OutputStream, @Nullable android.os.CancellationSignal, @Nullable java.util.concurrent.Executor, @Nullable android.os.FileUtils.ProgressListener) throws java.io.IOException;
method public static long copy(@NonNull java.io.FileDescriptor, @NonNull java.io.FileDescriptor) throws java.io.IOException;
@@ -34961,7 +34967,7 @@
method @Nullable public static android.os.Looper myLooper();
method @NonNull public static android.os.MessageQueue myQueue();
method public static void prepare();
- method public static void prepareMainLooper();
+ method @Deprecated public static void prepareMainLooper();
method public void quit();
method public void quitSafely();
method public void setMessageLogging(@Nullable android.util.Printer);
@@ -35908,6 +35914,7 @@
method public boolean isAllocationSupported(@NonNull java.io.FileDescriptor);
method public boolean isCacheBehaviorGroup(java.io.File) throws java.io.IOException;
method public boolean isCacheBehaviorTombstone(java.io.File) throws java.io.IOException;
+ method public boolean isCheckpointSupported();
method public boolean isEncrypted(java.io.File);
method public boolean isObbMounted(String);
method public boolean mountObb(String, String, android.os.storage.OnObbStateChangeListener);
@@ -48897,12 +48904,12 @@
method @Nullable public static java.util.List<java.lang.String> getTimeZoneIdsForCountryCode(@NonNull String);
}
- public class TimingLogger {
- ctor public TimingLogger(String, String);
- method public void addSplit(String);
- method public void dumpToLog();
- method public void reset(String, String);
- method public void reset();
+ @Deprecated public class TimingLogger {
+ ctor @Deprecated public TimingLogger(String, String);
+ method @Deprecated public void addSplit(String);
+ method @Deprecated public void dumpToLog();
+ method @Deprecated public void reset(String, String);
+ method @Deprecated public void reset();
}
public class TypedValue {
@@ -50815,7 +50822,7 @@
method public final int getScrollY();
method @android.view.ViewDebug.ExportedProperty(category="drawing") @ColorInt public int getSolidColor();
method @LayoutRes public int getSourceLayoutResId();
- method @android.view.ViewDebug.ExportedProperty(category="accessibility") @Nullable public CharSequence getStateDescription();
+ method @android.view.ViewDebug.ExportedProperty(category="accessibility") @Nullable public final CharSequence getStateDescription();
method public android.animation.StateListAnimator getStateListAnimator();
method protected int getSuggestedMinimumHeight();
method protected int getSuggestedMinimumWidth();
@@ -53448,6 +53455,23 @@
}
+package android.view.inline {
+
+ public final class InlinePresentationSpec implements android.os.Parcelable {
+ method public int describeContents();
+ method @NonNull public android.util.Size getMaxSize();
+ method @NonNull public android.util.Size getMinSize();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.view.inline.InlinePresentationSpec> CREATOR;
+ }
+
+ public static final class InlinePresentationSpec.Builder {
+ ctor public InlinePresentationSpec.Builder(@NonNull android.util.Size, @NonNull android.util.Size);
+ method @NonNull public android.view.inline.InlinePresentationSpec build();
+ }
+
+}
+
package android.view.inputmethod {
public class BaseInputConnection implements android.view.inputmethod.InputConnection {
@@ -53611,6 +53635,48 @@
field public int token;
}
+ public final class InlineSuggestion implements android.os.Parcelable {
+ method public int describeContents();
+ method @NonNull public android.view.inputmethod.InlineSuggestionInfo getInfo();
+ method public void inflate(@NonNull android.content.Context, @NonNull android.util.Size, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.view.View>);
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.view.inputmethod.InlineSuggestion> CREATOR;
+ }
+
+ public final class InlineSuggestionInfo implements android.os.Parcelable {
+ method public int describeContents();
+ method @Nullable public String[] getAutofillHints();
+ method @NonNull public android.view.inline.InlinePresentationSpec getPresentationSpec();
+ method @NonNull public String getSource();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.view.inputmethod.InlineSuggestionInfo> CREATOR;
+ field public static final String SOURCE_AUTOFILL = "android:autofill";
+ field public static final String SOURCE_PLATFORM = "android:platform";
+ }
+
+ public final class InlineSuggestionsRequest implements android.os.Parcelable {
+ method public int describeContents();
+ method public int getMaxSuggestionCount();
+ method @NonNull public java.util.List<android.view.inline.InlinePresentationSpec> getPresentationSpecs();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.view.inputmethod.InlineSuggestionsRequest> CREATOR;
+ field public static final int SUGGESTION_COUNT_UNLIMITED = 2147483647; // 0x7fffffff
+ }
+
+ public static final class InlineSuggestionsRequest.Builder {
+ ctor public InlineSuggestionsRequest.Builder(@NonNull java.util.List<android.view.inline.InlinePresentationSpec>);
+ method @NonNull public android.view.inputmethod.InlineSuggestionsRequest.Builder addPresentationSpecs(@NonNull android.view.inline.InlinePresentationSpec);
+ method @NonNull public android.view.inputmethod.InlineSuggestionsRequest build();
+ method @NonNull public android.view.inputmethod.InlineSuggestionsRequest.Builder setMaxSuggestionCount(int);
+ }
+
+ public final class InlineSuggestionsResponse implements android.os.Parcelable {
+ method public int describeContents();
+ method @NonNull public java.util.List<android.view.inputmethod.InlineSuggestion> getInlineSuggestions();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.view.inputmethod.InlineSuggestionsResponse> CREATOR;
+ }
+
public final class InputBinding implements android.os.Parcelable {
ctor public InputBinding(android.view.inputmethod.InputConnection, android.os.IBinder, int, int);
ctor public InputBinding(android.view.inputmethod.InputConnection, android.view.inputmethod.InputBinding);
@@ -57052,7 +57118,7 @@
method public int describeContents();
method public int getLayoutId();
method public String getPackage();
- method public boolean onLoadClass(Class);
+ method @Deprecated public boolean onLoadClass(Class);
method public void reapply(android.content.Context, android.view.View);
method public void removeAllViews(int);
method public void setAccessibilityTraversalAfter(int, int);
diff --git a/api/system-current.txt b/api/system-current.txt
index f74b743..b306c0f 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -604,6 +604,10 @@
method public void setNotificationAssistantAccessGranted(@Nullable android.content.ComponentName, boolean);
}
+ public class SearchManager implements android.content.DialogInterface.OnCancelListener android.content.DialogInterface.OnDismissListener {
+ method public void launchAssist(@Nullable android.os.Bundle);
+ }
+
public final class StatsManager {
method @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public void addConfig(long, byte[]) throws android.app.StatsManager.StatsUnavailableException;
method @Deprecated @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public boolean addConfiguration(long, byte[]);
@@ -1356,7 +1360,23 @@
method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) public boolean setPriority(android.bluetooth.BluetoothDevice, int);
}
+ public final class BluetoothPan implements android.bluetooth.BluetoothProfile {
+ method protected void finalize();
+ method @NonNull public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices();
+ method public int getConnectionState(@Nullable android.bluetooth.BluetoothDevice);
+ method public boolean isTetheringOn();
+ method public void setBluetoothTethering(boolean);
+ field public static final String ACTION_CONNECTION_STATE_CHANGED = "android.bluetooth.pan.profile.action.CONNECTION_STATE_CHANGED";
+ field public static final String EXTRA_LOCAL_ROLE = "android.bluetooth.pan.extra.LOCAL_ROLE";
+ field public static final int LOCAL_NAP_ROLE = 1; // 0x1
+ field public static final int LOCAL_PANU_ROLE = 2; // 0x2
+ field public static final int PAN_ROLE_NONE = 0; // 0x0
+ field public static final int REMOTE_NAP_ROLE = 1; // 0x1
+ field public static final int REMOTE_PANU_ROLE = 2; // 0x2
+ }
+
public interface BluetoothProfile {
+ field public static final int PAN = 5; // 0x5
field public static final int PRIORITY_OFF = 0; // 0x0
field public static final int PRIORITY_ON = 100; // 0x64
}
@@ -4183,6 +4203,33 @@
method public void onUpstreamChanged(@Nullable android.net.Network);
}
+ public final class IpConfiguration implements android.os.Parcelable {
+ ctor public IpConfiguration();
+ ctor public IpConfiguration(@NonNull android.net.IpConfiguration);
+ method @Nullable public android.net.ProxyInfo getHttpProxy();
+ method @NonNull public android.net.IpConfiguration.IpAssignment getIpAssignment();
+ method @NonNull public android.net.IpConfiguration.ProxySettings getProxySettings();
+ method @Nullable public android.net.StaticIpConfiguration getStaticIpConfiguration();
+ method public void setHttpProxy(@Nullable android.net.ProxyInfo);
+ method public void setIpAssignment(@NonNull android.net.IpConfiguration.IpAssignment);
+ method public void setProxySettings(@NonNull android.net.IpConfiguration.ProxySettings);
+ method public void setStaticIpConfiguration(@Nullable android.net.StaticIpConfiguration);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.IpConfiguration> CREATOR;
+ }
+
+ public enum IpConfiguration.IpAssignment {
+ enum_constant public static final android.net.IpConfiguration.IpAssignment DHCP;
+ enum_constant public static final android.net.IpConfiguration.IpAssignment STATIC;
+ enum_constant public static final android.net.IpConfiguration.IpAssignment UNASSIGNED;
+ }
+
+ public enum IpConfiguration.ProxySettings {
+ enum_constant public static final android.net.IpConfiguration.ProxySettings NONE;
+ enum_constant public static final android.net.IpConfiguration.ProxySettings PAC;
+ enum_constant public static final android.net.IpConfiguration.ProxySettings STATIC;
+ enum_constant public static final android.net.IpConfiguration.ProxySettings UNASSIGNED;
+ }
+
public final class IpPrefix implements android.os.Parcelable {
ctor public IpPrefix(@NonNull java.net.InetAddress, @IntRange(from=0, to=128) int);
ctor public IpPrefix(@NonNull String);
@@ -4255,6 +4302,7 @@
public class NetworkKey implements android.os.Parcelable {
ctor public NetworkKey(android.net.WifiKey);
+ method @Nullable public static android.net.NetworkKey createFromScanResult(@Nullable android.net.wifi.ScanResult);
method public int describeContents();
method public void writeToParcel(android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.net.NetworkKey> CREATOR;
@@ -4277,16 +4325,23 @@
method @RequiresPermission(anyOf={android.Manifest.permission.SCORE_NETWORKS, "android.permission.REQUEST_NETWORK_SCORES"}) public boolean clearScores() throws java.lang.SecurityException;
method @RequiresPermission(anyOf={android.Manifest.permission.SCORE_NETWORKS, "android.permission.REQUEST_NETWORK_SCORES"}) public void disableScoring() throws java.lang.SecurityException;
method @RequiresPermission(anyOf={android.Manifest.permission.SCORE_NETWORKS, "android.permission.REQUEST_NETWORK_SCORES"}) public String getActiveScorerPackage();
+ method @RequiresPermission("android.permission.REQUEST_NETWORK_SCORES") public void registerNetworkScoreCallback(int, int, @NonNull java.util.concurrent.Executor, @NonNull android.net.NetworkScoreManager.NetworkScoreCallback) throws java.lang.SecurityException;
+ method @RequiresPermission("android.permission.REQUEST_NETWORK_SCORES") public boolean requestScores(@NonNull android.net.NetworkKey[]) throws java.lang.SecurityException;
method @RequiresPermission(anyOf={android.Manifest.permission.SCORE_NETWORKS, "android.permission.REQUEST_NETWORK_SCORES"}) public boolean setActiveScorer(String) throws java.lang.SecurityException;
- method @RequiresPermission(android.Manifest.permission.SCORE_NETWORKS) public boolean updateScores(android.net.ScoredNetwork[]) throws java.lang.SecurityException;
- field public static final String ACTION_CHANGE_ACTIVE = "android.net.scoring.CHANGE_ACTIVE";
+ method @RequiresPermission(android.Manifest.permission.SCORE_NETWORKS) public boolean updateScores(@NonNull android.net.ScoredNetwork[]) throws java.lang.SecurityException;
+ field @Deprecated public static final String ACTION_CHANGE_ACTIVE = "android.net.scoring.CHANGE_ACTIVE";
field public static final String ACTION_CUSTOM_ENABLE = "android.net.scoring.CUSTOM_ENABLE";
field public static final String ACTION_RECOMMEND_NETWORKS = "android.net.action.RECOMMEND_NETWORKS";
field public static final String ACTION_SCORER_CHANGED = "android.net.scoring.SCORER_CHANGED";
- field public static final String ACTION_SCORE_NETWORKS = "android.net.scoring.SCORE_NETWORKS";
- field public static final String EXTRA_NETWORKS_TO_SCORE = "networksToScore";
+ field @Deprecated public static final String ACTION_SCORE_NETWORKS = "android.net.scoring.SCORE_NETWORKS";
+ field @Deprecated public static final String EXTRA_NETWORKS_TO_SCORE = "networksToScore";
field public static final String EXTRA_NEW_SCORER = "newScorer";
- field public static final String EXTRA_PACKAGE_NAME = "packageName";
+ field @Deprecated public static final String EXTRA_PACKAGE_NAME = "packageName";
+ }
+
+ public static interface NetworkScoreManager.NetworkScoreCallback {
+ method public void clearScores();
+ method public void updateScores(@NonNull java.util.List<android.net.ScoredNetwork>);
}
public class NetworkStack {
@@ -4408,6 +4463,258 @@
}
+package android.net.eap {
+
+ public final class EapSessionConfig {
+ }
+
+ public static final class EapSessionConfig.Builder {
+ ctor public EapSessionConfig.Builder();
+ method @NonNull public android.net.eap.EapSessionConfig build();
+ method @NonNull public android.net.eap.EapSessionConfig.Builder setEapAkaConfig(int, int);
+ method @NonNull public android.net.eap.EapSessionConfig.Builder setEapAkaPrimeConfig(int, int, @NonNull String, boolean);
+ method @NonNull public android.net.eap.EapSessionConfig.Builder setEapIdentity(@NonNull byte[]);
+ method @NonNull public android.net.eap.EapSessionConfig.Builder setEapMsChapV2Config(@NonNull String, @NonNull String);
+ method @NonNull public android.net.eap.EapSessionConfig.Builder setEapSimConfig(int, int);
+ }
+
+ public static class EapSessionConfig.EapAkaConfig extends android.net.eap.EapSessionConfig.EapUiccConfig {
+ }
+
+ public static class EapSessionConfig.EapAkaPrimeConfig extends android.net.eap.EapSessionConfig.EapAkaConfig {
+ method public boolean allowsMismatchedNetworkNames();
+ method @NonNull public String getNetworkName();
+ }
+
+ public abstract static class EapSessionConfig.EapMethodConfig {
+ method public int getMethodType();
+ }
+
+ public static class EapSessionConfig.EapMsChapV2Config extends android.net.eap.EapSessionConfig.EapMethodConfig {
+ method @NonNull public String getPassword();
+ method @NonNull public String getUsername();
+ }
+
+ public static class EapSessionConfig.EapSimConfig extends android.net.eap.EapSessionConfig.EapUiccConfig {
+ }
+
+ public abstract static class EapSessionConfig.EapUiccConfig extends android.net.eap.EapSessionConfig.EapMethodConfig {
+ method public int getAppType();
+ method public int getSubId();
+ }
+
+}
+
+package android.net.ipsec.ike {
+
+ public final class ChildSaProposal extends android.net.ipsec.ike.SaProposal {
+ }
+
+ public static final class ChildSaProposal.Builder {
+ ctor public ChildSaProposal.Builder();
+ method @NonNull public android.net.ipsec.ike.ChildSaProposal.Builder addDhGroup(int);
+ method @NonNull public android.net.ipsec.ike.ChildSaProposal.Builder addEncryptionAlgorithm(int, int);
+ method @NonNull public android.net.ipsec.ike.ChildSaProposal.Builder addIntegrityAlgorithm(int);
+ method @NonNull public android.net.ipsec.ike.ChildSaProposal build();
+ }
+
+ public interface ChildSessionCallback {
+ method public void onClosed();
+ method public void onClosedExceptionally(@NonNull android.net.ipsec.ike.exceptions.IkeException);
+ method public void onIpSecTransformCreated(@NonNull android.net.IpSecTransform, int);
+ method public void onIpSecTransformDeleted(@NonNull android.net.IpSecTransform, int);
+ method public void onOpened(@NonNull android.net.ipsec.ike.ChildSessionConfiguration);
+ }
+
+ public final class ChildSessionConfiguration {
+ method @NonNull public java.util.List<android.net.ipsec.ike.IkeTrafficSelector> getInboundTrafficSelectors();
+ method @NonNull public java.util.List<android.net.LinkAddress> getInternalAddresses();
+ method @NonNull public java.util.List<java.net.InetAddress> getInternalDhcpServers();
+ method @NonNull public java.util.List<java.net.InetAddress> getInternalDnsServers();
+ method @NonNull public java.util.List<android.net.LinkAddress> getInternalSubnets();
+ method @NonNull public java.util.List<android.net.ipsec.ike.IkeTrafficSelector> getOutboundTrafficSelectors();
+ }
+
+ public abstract class ChildSessionOptions {
+ }
+
+ public class IkeFqdnIdentification extends android.net.ipsec.ike.IkeIdentification {
+ ctor public IkeFqdnIdentification(@NonNull String);
+ field @NonNull public final String fqdn;
+ }
+
+ public abstract class IkeIdentification {
+ }
+
+ public final class IkeIpv4AddrIdentification extends android.net.ipsec.ike.IkeIdentification {
+ ctor public IkeIpv4AddrIdentification(@NonNull java.net.Inet4Address);
+ field @NonNull public final java.net.Inet4Address ipv4Address;
+ }
+
+ public class IkeIpv6AddrIdentification extends android.net.ipsec.ike.IkeIdentification {
+ ctor public IkeIpv6AddrIdentification(@NonNull java.net.Inet6Address);
+ field @NonNull public final java.net.Inet6Address ipv6Address;
+ }
+
+ public final class IkeKeyIdIdentification extends android.net.ipsec.ike.IkeIdentification {
+ ctor public IkeKeyIdIdentification(@NonNull byte[]);
+ field @NonNull public final byte[] keyId;
+ }
+
+ public final class IkeRfc822AddrIdentification extends android.net.ipsec.ike.IkeIdentification {
+ ctor public IkeRfc822AddrIdentification(@NonNull String);
+ field @NonNull public final String rfc822Name;
+ }
+
+ public final class IkeSaProposal extends android.net.ipsec.ike.SaProposal {
+ method @NonNull public java.util.List<java.lang.Integer> getPseudorandomFunctions();
+ }
+
+ public static final class IkeSaProposal.Builder {
+ ctor public IkeSaProposal.Builder();
+ method @NonNull public android.net.ipsec.ike.IkeSaProposal.Builder addDhGroup(int);
+ method @NonNull public android.net.ipsec.ike.IkeSaProposal.Builder addEncryptionAlgorithm(int, int);
+ method @NonNull public android.net.ipsec.ike.IkeSaProposal.Builder addIntegrityAlgorithm(int);
+ method @NonNull public android.net.ipsec.ike.IkeSaProposal.Builder addPseudorandomFunction(int);
+ method @NonNull public android.net.ipsec.ike.IkeSaProposal build();
+ }
+
+ public final class IkeSession implements java.lang.AutoCloseable {
+ ctor public IkeSession(@NonNull android.content.Context, @NonNull android.net.ipsec.ike.IkeSessionOptions, @NonNull android.net.ipsec.ike.ChildSessionOptions, @NonNull java.util.concurrent.Executor, @NonNull android.net.ipsec.ike.IkeSessionCallback, @NonNull android.net.ipsec.ike.ChildSessionCallback);
+ method public void close();
+ method public void closeChildSession(@NonNull android.net.ipsec.ike.ChildSessionCallback);
+ method public void kill();
+ method public void openChildSession(@NonNull android.net.ipsec.ike.ChildSessionOptions, @NonNull android.net.ipsec.ike.ChildSessionCallback);
+ }
+
+ public interface IkeSessionCallback {
+ method public void onClosed();
+ method public void onClosedExceptionally(@NonNull android.net.ipsec.ike.exceptions.IkeException);
+ method public void onError(@NonNull android.net.ipsec.ike.exceptions.IkeProtocolException);
+ method public void onOpened(@NonNull android.net.ipsec.ike.IkeSessionConfiguration);
+ }
+
+ public final class IkeSessionConfiguration {
+ ctor public IkeSessionConfiguration();
+ method @NonNull public String getRemoteApplicationVersion();
+ method public boolean isIkeExtensionEnabled(int);
+ field public static final int EXTENSION_TYPE_FRAGMENTATION = 1; // 0x1
+ field public static final int EXTENSION_TYPE_MOBIKE = 2; // 0x2
+ }
+
+ public final class IkeSessionOptions {
+ }
+
+ public static final class IkeSessionOptions.Builder {
+ ctor public IkeSessionOptions.Builder();
+ method @NonNull public android.net.ipsec.ike.IkeSessionOptions.Builder addSaProposal(@NonNull android.net.ipsec.ike.IkeSaProposal);
+ method @NonNull public android.net.ipsec.ike.IkeSessionOptions build();
+ method @NonNull public android.net.ipsec.ike.IkeSessionOptions.Builder setAuthDigitalSignature(@NonNull java.security.cert.X509Certificate, @NonNull java.security.cert.X509Certificate, @NonNull java.security.PrivateKey);
+ method @NonNull public android.net.ipsec.ike.IkeSessionOptions.Builder setAuthDigitalSignature(@NonNull java.security.cert.X509Certificate, @NonNull java.security.cert.X509Certificate, @NonNull java.util.List<java.security.cert.X509Certificate>, @NonNull java.security.PrivateKey);
+ method @NonNull public android.net.ipsec.ike.IkeSessionOptions.Builder setAuthEap(@NonNull java.security.cert.X509Certificate, @NonNull android.net.eap.EapSessionConfig);
+ method @NonNull public android.net.ipsec.ike.IkeSessionOptions.Builder setAuthPsk(@NonNull byte[]);
+ method @NonNull public android.net.ipsec.ike.IkeSessionOptions.Builder setLocalIdentification(@NonNull android.net.ipsec.ike.IkeIdentification);
+ method @NonNull public android.net.ipsec.ike.IkeSessionOptions.Builder setRemoteIdentification(@NonNull android.net.ipsec.ike.IkeIdentification);
+ method @NonNull public android.net.ipsec.ike.IkeSessionOptions.Builder setServerAddress(@NonNull java.net.InetAddress);
+ method @NonNull public android.net.ipsec.ike.IkeSessionOptions.Builder setUdpEncapsulationSocket(@NonNull android.net.IpSecManager.UdpEncapsulationSocket);
+ }
+
+ public final class IkeTrafficSelector {
+ ctor public IkeTrafficSelector(int, int, @NonNull java.net.InetAddress, @NonNull java.net.InetAddress);
+ field public final int endPort;
+ field @NonNull public final java.net.InetAddress endingAddress;
+ field public final int startPort;
+ field @NonNull public final java.net.InetAddress startingAddress;
+ }
+
+ public abstract class SaProposal {
+ method @NonNull public java.util.List<java.lang.Integer> getDhGroups();
+ method @NonNull public java.util.List<android.util.Pair<java.lang.Integer,java.lang.Integer>> getEncryptionAlgorithms();
+ method @NonNull public java.util.List<java.lang.Integer> getIntegrityAlgorithms();
+ field public static final int DH_GROUP_1024_BIT_MODP = 2; // 0x2
+ field public static final int DH_GROUP_2048_BIT_MODP = 14; // 0xe
+ field public static final int DH_GROUP_NONE = 0; // 0x0
+ field public static final int ENCRYPTION_ALGORITHM_3DES = 3; // 0x3
+ field public static final int ENCRYPTION_ALGORITHM_AES_CBC = 12; // 0xc
+ field public static final int ENCRYPTION_ALGORITHM_AES_GCM_12 = 19; // 0x13
+ field public static final int ENCRYPTION_ALGORITHM_AES_GCM_16 = 20; // 0x14
+ field public static final int ENCRYPTION_ALGORITHM_AES_GCM_8 = 18; // 0x12
+ field public static final int INTEGRITY_ALGORITHM_AES_XCBC_96 = 5; // 0x5
+ field public static final int INTEGRITY_ALGORITHM_HMAC_SHA1_96 = 2; // 0x2
+ field public static final int INTEGRITY_ALGORITHM_HMAC_SHA2_256_128 = 12; // 0xc
+ field public static final int INTEGRITY_ALGORITHM_HMAC_SHA2_384_192 = 13; // 0xd
+ field public static final int INTEGRITY_ALGORITHM_HMAC_SHA2_512_256 = 14; // 0xe
+ field public static final int INTEGRITY_ALGORITHM_NONE = 0; // 0x0
+ field public static final int KEY_LEN_AES_128 = 128; // 0x80
+ field public static final int KEY_LEN_AES_192 = 192; // 0xc0
+ field public static final int KEY_LEN_AES_256 = 256; // 0x100
+ field public static final int KEY_LEN_UNUSED = 0; // 0x0
+ field public static final int PSEUDORANDOM_FUNCTION_AES128_XCBC = 4; // 0x4
+ field public static final int PSEUDORANDOM_FUNCTION_HMAC_SHA1 = 2; // 0x2
+ }
+
+ public final class TransportModeChildSessionOptions extends android.net.ipsec.ike.ChildSessionOptions {
+ }
+
+ public static final class TransportModeChildSessionOptions.Builder {
+ ctor public TransportModeChildSessionOptions.Builder();
+ method @NonNull public android.net.ipsec.ike.TransportModeChildSessionOptions.Builder addInboundTrafficSelectors(@NonNull android.net.ipsec.ike.IkeTrafficSelector);
+ method @NonNull public android.net.ipsec.ike.TransportModeChildSessionOptions.Builder addOutboundTrafficSelectors(@NonNull android.net.ipsec.ike.IkeTrafficSelector);
+ method @NonNull public android.net.ipsec.ike.TransportModeChildSessionOptions.Builder addSaProposal(@NonNull android.net.ipsec.ike.ChildSaProposal);
+ method @NonNull public android.net.ipsec.ike.TransportModeChildSessionOptions build();
+ }
+
+ public final class TunnelModeChildSessionOptions extends android.net.ipsec.ike.ChildSessionOptions {
+ }
+
+ public static final class TunnelModeChildSessionOptions.Builder {
+ ctor public TunnelModeChildSessionOptions.Builder();
+ method @NonNull public android.net.ipsec.ike.TunnelModeChildSessionOptions.Builder addInboundTrafficSelectors(@NonNull android.net.ipsec.ike.IkeTrafficSelector);
+ method @NonNull public android.net.ipsec.ike.TunnelModeChildSessionOptions.Builder addInternalAddressRequest(int);
+ method @NonNull public android.net.ipsec.ike.TunnelModeChildSessionOptions.Builder addInternalAddressRequest(@NonNull java.net.InetAddress, int);
+ method @NonNull public android.net.ipsec.ike.TunnelModeChildSessionOptions.Builder addInternalDhcpServerRequest(int);
+ method @NonNull public android.net.ipsec.ike.TunnelModeChildSessionOptions.Builder addInternalDhcpServerRequest(@NonNull java.net.InetAddress);
+ method @NonNull public android.net.ipsec.ike.TunnelModeChildSessionOptions.Builder addInternalDnsServerRequest(int);
+ method @NonNull public android.net.ipsec.ike.TunnelModeChildSessionOptions.Builder addInternalDnsServerRequest(@NonNull java.net.InetAddress);
+ method @NonNull public android.net.ipsec.ike.TunnelModeChildSessionOptions.Builder addInternalSubnetRequest(int);
+ method @NonNull public android.net.ipsec.ike.TunnelModeChildSessionOptions.Builder addOutboundTrafficSelectors(@NonNull android.net.ipsec.ike.IkeTrafficSelector);
+ method @NonNull public android.net.ipsec.ike.TunnelModeChildSessionOptions.Builder addSaProposal(@NonNull android.net.ipsec.ike.ChildSaProposal);
+ method @NonNull public android.net.ipsec.ike.TunnelModeChildSessionOptions build();
+ }
+
+}
+
+package android.net.ipsec.ike.exceptions {
+
+ public abstract class IkeException extends java.lang.Exception {
+ }
+
+ public final class IkeInternalException extends android.net.ipsec.ike.exceptions.IkeException {
+ }
+
+ public abstract class IkeProtocolException extends android.net.ipsec.ike.exceptions.IkeException {
+ method @Nullable public byte[] getErrorData();
+ method public int getErrorType();
+ field public static final int ERROR_TYPE_AUTHENTICATION_FAILED = 24; // 0x18
+ field public static final int ERROR_TYPE_CHILD_SA_NOT_FOUND = 44; // 0x2c
+ field public static final int ERROR_TYPE_FAILED_CP_REQUIRED = 37; // 0x25
+ field public static final int ERROR_TYPE_INTERNAL_ADDRESS_FAILURE = 36; // 0x24
+ field public static final int ERROR_TYPE_INVALID_IKE_SPI = 4; // 0x4
+ field public static final int ERROR_TYPE_INVALID_KE_PAYLOAD = 17; // 0x11
+ field public static final int ERROR_TYPE_INVALID_MAJOR_VERSION = 5; // 0x5
+ field public static final int ERROR_TYPE_INVALID_MESSAGE_ID = 9; // 0x9
+ field public static final int ERROR_TYPE_INVALID_SELECTORS = 39; // 0x27
+ field public static final int ERROR_TYPE_INVALID_SYNTAX = 7; // 0x7
+ field public static final int ERROR_TYPE_NO_ADDITIONAL_SAS = 35; // 0x23
+ field public static final int ERROR_TYPE_NO_PROPOSAL_CHOSEN = 14; // 0xe
+ field public static final int ERROR_TYPE_SINGLE_PAIR_REQUIRED = 34; // 0x22
+ field public static final int ERROR_TYPE_TEMPORARY_FAILURE = 43; // 0x2b
+ field public static final int ERROR_TYPE_TS_UNACCEPTABLE = 38; // 0x26
+ field public static final int ERROR_TYPE_UNSUPPORTED_CRITICAL_PAYLOAD = 1; // 0x1
+ }
+
+}
+
package android.net.metrics {
public final class ApfProgramEvent implements android.net.metrics.IpConnectivityLog.Event {
@@ -4853,6 +5160,10 @@
field @Deprecated public static final int WPA2_PSK = 4; // 0x4
}
+ public class WifiFrameworkInitializer {
+ method public static void registerServiceWrappers();
+ }
+
public class WifiInfo implements android.os.Parcelable {
method @Nullable public String getAppPackageName();
method public double getRxSuccessRate();
@@ -5024,6 +5335,7 @@
method @NonNull @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public java.util.List<java.lang.Integer> getAvailableChannels(int);
method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public boolean getScanResults();
method @NonNull @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public java.util.List<android.net.wifi.ScanResult> getSingleScanResults();
+ method @RequiresPermission(android.Manifest.permission.NETWORK_STACK) public void setScanningEnabled(boolean);
method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public void startBackgroundScan(android.net.wifi.WifiScanner.ScanSettings, android.net.wifi.WifiScanner.ScanListener);
method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public void startBackgroundScan(android.net.wifi.WifiScanner.ScanSettings, android.net.wifi.WifiScanner.ScanListener, android.os.WorkSource);
method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public void startScan(android.net.wifi.WifiScanner.ScanSettings, android.net.wifi.WifiScanner.ScanListener);
@@ -5489,6 +5801,17 @@
method @NonNull public static java.io.File getVendorDirectory();
}
+ public class HidlMemory implements java.io.Closeable {
+ ctor public HidlMemory(@NonNull String, @IntRange(from=0) long, @Nullable android.os.NativeHandle);
+ method public void close() throws java.io.IOException;
+ method @NonNull public android.os.HidlMemory dup() throws java.io.IOException;
+ method protected void finalize();
+ method @Nullable public android.os.NativeHandle getHandle();
+ method @NonNull public String getName();
+ method public long getSize();
+ method @NonNull public android.os.NativeHandle releaseHandle();
+ }
+
public class HidlSupport {
method public static boolean deepEquals(Object, Object);
method public static int deepHashCode(Object);
@@ -5519,6 +5842,7 @@
method public final void copyToInt8Array(long, byte[], int);
method public final boolean getBool(long);
method public final double getDouble(long);
+ method public final long getFieldHandle(long);
method public final float getFloat(long);
method public final short getInt16(long);
method public final int getInt32(long);
@@ -5533,6 +5857,7 @@
method public final void putDoubleArray(long, double[]);
method public final void putFloat(long, float);
method public final void putFloatArray(long, float[]);
+ method public final void putHidlMemory(long, @NonNull android.os.HidlMemory);
method public final void putInt16(long, short);
method public final void putInt16Array(long, short[]);
method public final void putInt32(long, int);
@@ -5561,9 +5886,11 @@
method public final double readDouble();
method public final java.util.ArrayList<java.lang.Double> readDoubleVector();
method public final android.os.HwBlob readEmbeddedBuffer(long, long, long, boolean);
+ method @NonNull @Nullable public final android.os.HidlMemory readEmbeddedHidlMemory(long, long, long);
method @Nullable public final android.os.NativeHandle readEmbeddedNativeHandle(long, long);
method public final float readFloat();
method public final java.util.ArrayList<java.lang.Float> readFloatVector();
+ method @NonNull public final android.os.HidlMemory readHidlMemory();
method public final short readInt16();
method public final java.util.ArrayList<java.lang.Short> readInt16Vector();
method public final int readInt32();
@@ -5588,6 +5915,7 @@
method public final void writeDoubleVector(java.util.ArrayList<java.lang.Double>);
method public final void writeFloat(float);
method public final void writeFloatVector(java.util.ArrayList<java.lang.Float>);
+ method public final void writeHidlMemory(@NonNull android.os.HidlMemory);
method public final void writeInt16(short);
method public final void writeInt16Vector(java.util.ArrayList<java.lang.Short>);
method public final void writeInt32(int);
@@ -5712,6 +6040,9 @@
field public static final int USER_ACTIVITY_FLAG_NO_CHANGE_LIGHTS = 1; // 0x1
}
+ public class PowerWhitelistManager {
+ }
+
public class RecoverySystem {
method @RequiresPermission(android.Manifest.permission.RECOVERY) public static void cancelScheduledUpdate(android.content.Context) throws java.io.IOException;
method @RequiresPermission(android.Manifest.permission.RECOVERY) public static void installPackage(android.content.Context, java.io.File, boolean) throws java.io.IOException;
@@ -6214,6 +6545,7 @@
method @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public static String getString(@NonNull String, @NonNull String, @Nullable String);
method public static void removeOnPropertiesChangedListener(@NonNull android.provider.DeviceConfig.OnPropertiesChangedListener);
method @RequiresPermission(android.Manifest.permission.WRITE_DEVICE_CONFIG) public static void resetToDefaults(int, @Nullable String);
+ method @RequiresPermission(android.Manifest.permission.WRITE_DEVICE_CONFIG) public static boolean setProperties(@NonNull android.provider.DeviceConfig.Properties);
method @RequiresPermission(android.Manifest.permission.WRITE_DEVICE_CONFIG) public static boolean setProperty(@NonNull String, @NonNull String, @Nullable String, boolean);
field public static final String NAMESPACE_ACTIVITY_MANAGER = "activity_manager";
field public static final String NAMESPACE_ACTIVITY_MANAGER_NATIVE_BOOT = "activity_manager_native_boot";
@@ -6420,7 +6752,7 @@
public static final class Settings.Secure extends android.provider.Settings.NameValueTable {
method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public static boolean putString(@NonNull android.content.ContentResolver, @NonNull String, @Nullable String, @Nullable String, boolean);
method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public static void resetToDefaults(@NonNull android.content.ContentResolver, @Nullable String);
- field public static final String ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED = "accessibility_display_magnification_navbar_enabled";
+ field @Deprecated public static final String ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED = "accessibility_display_magnification_navbar_enabled";
field public static final String ASSIST_GESTURE_SETUP_COMPLETE = "assist_gesture_setup_complete";
field public static final String AUTOFILL_FEATURE_FIELD_CLASSIFICATION = "autofill_field_classification";
field public static final String AUTOFILL_USER_DATA_MAX_CATEGORY_COUNT = "autofill_user_data_max_category_count";
@@ -6524,6 +6856,7 @@
field public static final String SERIAL_NUMBER = "serial_number";
field public static final String SERVICE_CATEGORY = "service_category";
field public static final String SLOT_INDEX = "slot_index";
+ field public static final String SUB_ID = "sub_id";
}
public static final class Telephony.Sms.Intents {
@@ -8583,7 +8916,7 @@
}
public final class SmsCbMessage implements android.os.Parcelable {
- ctor public SmsCbMessage(int, int, int, @NonNull android.telephony.SmsCbLocation, int, @Nullable String, @Nullable String, int, @Nullable android.telephony.SmsCbEtwsInfo, @Nullable android.telephony.SmsCbCmasInfo, int, @Nullable java.util.List<android.telephony.CbGeoUtils.Geometry>, long, int);
+ ctor public SmsCbMessage(int, int, int, @NonNull android.telephony.SmsCbLocation, int, @Nullable String, @Nullable String, int, @Nullable android.telephony.SmsCbEtwsInfo, @Nullable android.telephony.SmsCbCmasInfo, int, @Nullable java.util.List<android.telephony.CbGeoUtils.Geometry>, long, int, int);
method @NonNull public static android.telephony.SmsCbMessage createFromCursor(@NonNull android.database.Cursor);
method public int describeContents();
method @Nullable public android.telephony.SmsCbCmasInfo getCmasWarningInfo();
@@ -8600,6 +8933,7 @@
method public int getSerialNumber();
method public int getServiceCategory();
method public int getSlotIndex();
+ method public int getSubscriptionId();
method public boolean isCmasMessage();
method public boolean isEmergencyMessage();
method public boolean isEtwsMessage();
@@ -8719,6 +9053,7 @@
method @NonNull public static String getDefaultSimCountryIso();
method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getDeviceSoftwareVersion(int);
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean getEmergencyCallbackMode();
+ method public int getEmergencyNumberDbVersion();
method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getIsimDomain();
method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getIsimIst();
method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.Map<java.lang.Integer,java.lang.Integer> getLogicalToPhysicalSlotMapping();
@@ -8758,6 +9093,7 @@
method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isVideoCallingEnabled();
method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public boolean isVisualVoicemailEnabled(android.telecom.PhoneAccountHandle);
method public boolean needsOtaServiceProvisioning();
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void notifyOtaEmergencyNumberDbInstalled();
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean rebootRadio();
method @RequiresPermission(allOf={android.Manifest.permission.ACCESS_FINE_LOCATION, android.Manifest.permission.MODIFY_PHONE_STATE}) public void requestCellInfoUpdate(@NonNull android.os.WorkSource, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.TelephonyManager.CellInfoCallback);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void requestNumberVerification(@NonNull android.telephony.PhoneNumberRange, long, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.NumberVerificationCallback);
@@ -8786,8 +9122,8 @@
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean switchSlots(int[]);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void toggleRadioOnOff();
method public void updateServiceLocation();
+ method @RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) public void updateTestOtaEmergencyNumberDbFilePath(@NonNull String);
field @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public static final String ACTION_ANOMALY_REPORTED = "android.telephony.action.ANOMALY_REPORTED";
- field @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public static final String ACTION_OTA_EMERGENCY_NUMBER_DB_INSTALLED = "android.telephony.action.OTA_EMERGENCY_NUMBER_DB_INSTALLED";
field public static final String ACTION_SIM_APPLICATION_STATE_CHANGED = "android.telephony.action.SIM_APPLICATION_STATE_CHANGED";
field public static final String ACTION_SIM_CARD_STATE_CHANGED = "android.telephony.action.SIM_CARD_STATE_CHANGED";
field public static final String ACTION_SIM_SLOT_STATUS_CHANGED = "android.telephony.action.SIM_SLOT_STATUS_CHANGED";
@@ -8800,6 +9136,7 @@
field public static final String EXTRA_SIM_STATE = "android.telephony.extra.SIM_STATE";
field public static final String EXTRA_VISUAL_VOICEMAIL_ENABLED_BY_USER_BOOL = "android.telephony.extra.VISUAL_VOICEMAIL_ENABLED_BY_USER_BOOL";
field public static final String EXTRA_VOICEMAIL_SCRAMBLED_PIN_STRING = "android.telephony.extra.VOICEMAIL_SCRAMBLED_PIN_STRING";
+ field public static final int INVALID_EMERGENCY_NUMBER_DB_VERSION = -1; // 0xffffffff
field public static final int KEY_TYPE_EPDG = 1; // 0x1
field public static final int KEY_TYPE_WLAN = 2; // 0x2
field public static final long NETWORK_TYPE_BITMASK_1xRTT = 64L; // 0x40L
diff --git a/api/test-current.txt b/api/test-current.txt
index 95b0cae..dacc5d6 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -707,6 +707,7 @@
field public static final String CONTENT_CAPTURE_MANAGER_SERVICE = "content_capture";
field public static final String DEVICE_IDLE_CONTROLLER = "deviceidle";
field public static final String PERMISSION_SERVICE = "permission";
+ field public static final String POWER_WHITELIST_MANAGER = "power_whitelist";
field public static final String ROLLBACK_SERVICE = "rollback";
field public static final String STATUS_BAR_SERVICE = "statusbar";
field public static final String TEST_NETWORK_SERVICE = "test_network";
@@ -1808,6 +1809,17 @@
method public static boolean contains(java.io.File, java.io.File);
}
+ public class HidlMemory implements java.io.Closeable {
+ ctor public HidlMemory(@NonNull String, @IntRange(from=0) long, @Nullable android.os.NativeHandle);
+ method public void close() throws java.io.IOException;
+ method @NonNull public android.os.HidlMemory dup() throws java.io.IOException;
+ method protected void finalize();
+ method @Nullable public android.os.NativeHandle getHandle();
+ method @NonNull public String getName();
+ method public long getSize();
+ method @NonNull public android.os.NativeHandle releaseHandle();
+ }
+
public abstract class HwBinder implements android.os.IHwBinder {
ctor public HwBinder();
method public static final void configureRpcThreadpool(long, boolean);
@@ -1831,6 +1843,7 @@
method public final void copyToInt8Array(long, byte[], int);
method public final boolean getBool(long);
method public final double getDouble(long);
+ method public final long getFieldHandle(long);
method public final float getFloat(long);
method public final short getInt16(long);
method public final int getInt32(long);
@@ -1845,6 +1858,7 @@
method public final void putDoubleArray(long, double[]);
method public final void putFloat(long, float);
method public final void putFloatArray(long, float[]);
+ method public final void putHidlMemory(long, @NonNull android.os.HidlMemory);
method public final void putInt16(long, short);
method public final void putInt16Array(long, short[]);
method public final void putInt32(long, int);
@@ -1873,9 +1887,11 @@
method public final double readDouble();
method public final java.util.ArrayList<java.lang.Double> readDoubleVector();
method public final android.os.HwBlob readEmbeddedBuffer(long, long, long, boolean);
+ method @NonNull @Nullable public final android.os.HidlMemory readEmbeddedHidlMemory(long, long, long);
method @Nullable public final android.os.NativeHandle readEmbeddedNativeHandle(long, long);
method public final float readFloat();
method public final java.util.ArrayList<java.lang.Float> readFloatVector();
+ method @NonNull public final android.os.HidlMemory readHidlMemory();
method public final short readInt16();
method public final java.util.ArrayList<java.lang.Short> readInt16Vector();
method public final int readInt32();
@@ -1900,6 +1916,7 @@
method public final void writeDoubleVector(java.util.ArrayList<java.lang.Double>);
method public final void writeFloat(float);
method public final void writeFloatVector(java.util.ArrayList<java.lang.Float>);
+ method public final void writeHidlMemory(@NonNull android.os.HidlMemory);
method public final void writeInt16(short);
method public final void writeInt16Vector(java.util.ArrayList<java.lang.Short>);
method public final void writeInt32(int);
@@ -2026,6 +2043,9 @@
field public static final int POWER_SAVE_MODE_TRIGGER_PERCENTAGE = 0; // 0x0
}
+ public class PowerWhitelistManager {
+ }
+
public class Process {
method public static final int getThreadScheduler(int) throws java.lang.IllegalArgumentException;
field public static final int FIRST_APP_ZYGOTE_ISOLATED_UID = 90000; // 0x15f90
@@ -2449,6 +2469,7 @@
field public static final String DYNAMIC_POWER_SAVINGS_DISABLE_THRESHOLD = "dynamic_power_savings_disable_threshold";
field public static final String DYNAMIC_POWER_SAVINGS_ENABLED = "dynamic_power_savings_enabled";
field public static final String HIDDEN_API_BLACKLIST_EXEMPTIONS = "hidden_api_blacklist_exemptions";
+ field public static final String HIDE_ERROR_DIALOGS = "hide_error_dialogs";
field public static final String LOCATION_GLOBAL_KILL_SWITCH = "location_global_kill_switch";
field public static final String LOCATION_IGNORE_SETTINGS_PACKAGE_WHITELIST = "location_ignore_settings_package_whitelist";
field public static final String LOW_POWER_MODE = "low_power";
@@ -2510,6 +2531,7 @@
field public static final String SERIAL_NUMBER = "serial_number";
field public static final String SERVICE_CATEGORY = "service_category";
field public static final String SLOT_INDEX = "slot_index";
+ field public static final String SUB_ID = "sub_id";
}
public static final class Telephony.Sms.Intents {
@@ -3135,16 +3157,19 @@
method public int getCarrierIdListVersion();
method public java.util.List<java.lang.String> getCarrierPackageNamesForIntent(android.content.Intent);
method @Nullable public static android.content.ComponentName getDefaultRespondViaMessageApplication(@NonNull android.content.Context, boolean);
+ method public int getEmergencyNumberDbVersion();
method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public String getLine1AlphaTag();
method @NonNull @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public String getNetworkCountryIso(int);
method public android.util.Pair<java.lang.Integer,java.lang.Integer> getRadioHalVersion();
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void refreshUiccProfile();
method @Deprecated public void setCarrierTestOverride(String, String, String, String, String, String, String);
method public void setCarrierTestOverride(String, String, String, String, String, String, String, String, String);
+ method @RequiresPermission("android.permission.READ_ACTIVE_EMERGENCY_SESSION") public void updateTestOtaEmergencyNumberDbFilePath(@NonNull String);
field public static final int CARRIER_PRIVILEGE_STATUS_ERROR_LOADING_RULES = -2; // 0xfffffffe
field public static final int CARRIER_PRIVILEGE_STATUS_HAS_ACCESS = 1; // 0x1
field public static final int CARRIER_PRIVILEGE_STATUS_NO_ACCESS = 0; // 0x0
field public static final int CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED = -1; // 0xffffffff
+ field public static final int INVALID_EMERGENCY_NUMBER_DB_VERSION = -1; // 0xffffffff
field public static final int UNKNOWN_CARRIER_ID_LIST_VERSION = -1; // 0xffffffff
}
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index b0570fd..49cc3c4 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -164,7 +164,7 @@
BiometricAcquired biometric_acquired = 87;
BiometricAuthenticated biometric_authenticated = 88;
BiometricErrorOccurred biometric_error_occurred = 89;
- // Atom number 90 is available for use.
+ UiEventReported ui_event_reported = 90;
BatteryHealthSnapshot battery_health_snapshot = 91;
SlowIo slow_io = 92;
BatteryCausedShutdown battery_caused_shutdown = 93;
@@ -340,6 +340,8 @@
PerfettoUploaded perfetto_uploaded =
229 [(log_from_module) = "perfetto"];
VmsClientConnectionStateChanged vms_client_connection_state_changed = 230;
+ GpsLocationStatusReported gps_location_status_reported = 231;
+ GpsTimeToFirstFixReported gps_time_to_first_fix_reported = 232;
}
// Pulled events will start at field 10000.
@@ -734,6 +736,27 @@
optional android.server.location.GpsSignalQualityEnum level = 1;
}
+/**
+ * Gps location status report
+ *
+ * Logged from:
+ * /frameworks/base/location/java/com/android/internal/location/gnssmetrics/GnssMetrics.java
+ */
+message GpsLocationStatusReported {
+ // Boolean stating if location was acquired
+ optional bool location_success = 1;
+}
+
+/**
+ * Gps log time to first fix report
+ *
+ * Logged from:
+ * /frameworks/base/location/java/com/android/internal/location/gnssmetrics/GnssMetrics.java
+ */
+message GpsTimeToFirstFixReported {
+ // int32 reporting the time to first fix in milliseconds
+ optional int32 time_to_first_fix_millis = 1;
+}
/**
* Logs when a sync manager sync state changes.
@@ -3266,6 +3289,21 @@
}
/**
+ * Atom for simple logging of user interaction and impression events, such as "the user touched
+ * this button" or "this dialog was displayed".
+ * Keep the UI event stream clean: don't use for system or background events.
+ * Log using the UiEventLogger wrapper - don't write with the StatsLog API directly.
+ */
+message UiEventReported {
+ // The event_id.
+ optional int32 event_id = 1;
+ // The event's source or target uid and package, if applicable.
+ // For example, the package posting a notification, or the destination package of a share.
+ optional int32 uid = 2 [(is_uid) = true];
+ optional string package_name = 3;
+}
+
+/**
* Logs when a biometric acquire event occurs.
*
* Logged from:
diff --git a/cmds/statsd/src/external/StatsPullerManager.cpp b/cmds/statsd/src/external/StatsPullerManager.cpp
index ce27ce6..b5bad05 100644
--- a/cmds/statsd/src/external/StatsPullerManager.cpp
+++ b/cmds/statsd/src/external/StatsPullerManager.cpp
@@ -499,8 +499,9 @@
StatsdStats::getInstance().notePullerCallbackRegistrationChanged(atomTag, /*registered=*/true);
kAllPullAtomInfo[{.atomTag = atomTag}] = {.additiveFields = additiveFields,
.coolDownNs = coolDownNs,
+ .puller = new StatsCallbackPuller(atomTag, callback),
.pullTimeoutNs = timeoutNs,
- .puller = new StatsCallbackPuller(atomTag, callback)};
+ };
}
void StatsPullerManager::UnregisterPullerCallback(int32_t atomTag) {
diff --git a/cmds/svc/src/com/android/commands/svc/Svc.java b/cmds/svc/src/com/android/commands/svc/Svc.java
index 68fb8e6..e602e2a 100644
--- a/cmds/svc/src/com/android/commands/svc/Svc.java
+++ b/cmds/svc/src/com/android/commands/svc/Svc.java
@@ -94,7 +94,7 @@
COMMAND_HELP,
new PowerCommand(),
new DataCommand(),
- new WifiCommand(),
+ // `svc wifi` has been migrated to WifiShellCommand
new UsbCommand(),
new NfcCommand(),
new BluetoothCommand(),
diff --git a/cmds/svc/src/com/android/commands/svc/WifiCommand.java b/cmds/svc/src/com/android/commands/svc/WifiCommand.java
deleted file mode 100644
index e31cb53..0000000
--- a/cmds/svc/src/com/android/commands/svc/WifiCommand.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (C) 2008 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.commands.svc;
-
-import android.os.ServiceManager;
-import android.os.RemoteException;
-import android.net.wifi.IWifiManager;
-import android.content.Context;
-
-public class WifiCommand extends Svc.Command {
- public WifiCommand() {
- super("wifi");
- }
-
- public String shortHelp() {
- return "Control the Wi-Fi manager";
- }
-
- public String longHelp() {
- return shortHelp() + "\n"
- + "\n"
- + "usage: svc wifi [enable|disable]\n"
- + " Turn Wi-Fi on or off.\n\n";
- }
-
- public void run(String[] args) {
- boolean validCommand = false;
- if (args.length >= 2) {
- boolean flag = false;
- if ("enable".equals(args[1])) {
- flag = true;
- validCommand = true;
- } else if ("disable".equals(args[1])) {
- flag = false;
- validCommand = true;
- }
- if (validCommand) {
- IWifiManager wifiMgr
- = IWifiManager.Stub.asInterface(ServiceManager.getService(Context.WIFI_SERVICE));
- if (wifiMgr == null) {
- System.err.println("Wi-Fi service is not ready");
- return;
- }
- try {
- wifiMgr.setWifiEnabled("com.android.shell", flag);
- }
- catch (RemoteException e) {
- System.err.println("Wi-Fi operation failed: " + e);
- }
- return;
- }
- }
- System.err.println(longHelp());
- }
-}
diff --git a/cmds/svc/svc b/cmds/svc/svc
index c122e98..60c95c7 100755
--- a/cmds/svc/svc
+++ b/cmds/svc/svc
@@ -1,3 +1,24 @@
#!/system/bin/sh
+
+# `svc wifi` has been migrated to WifiShellCommand,
+# simply perform translation to `cmd wifi set-wifi-enabled` here.
+if [ "x$1" == "xwifi" ]; then
+ # `cmd wifi` by convention uses enabled/disabled
+ # instead of enable/disable
+ if [ "x$2" == "xenable" ]; then
+ exec cmd wifi set-wifi-enabled enabled
+ elif [ "x$2" == "xdisable" ]; then
+ exec cmd wifi set-wifi-enabled disabled
+ else
+ echo "Control the Wi-Fi manager"
+ echo ""
+ echo "usage: svc wifi [enable|disable]"
+ echo " Turn Wi-Fi on or off."
+ echo ""
+ fi
+ exit 1
+fi
+
export CLASSPATH=/system/framework/svc.jar
exec app_process /system/bin com.android.commands.svc.Svc "$@"
+
diff --git a/config/preloaded-classes b/config/preloaded-classes
index ab98e5b..0394a7a 100644
--- a/config/preloaded-classes
+++ b/config/preloaded-classes
@@ -514,6 +514,7 @@
android.app.admin.SystemUpdateInfo
android.app.admin.SystemUpdatePolicy$1
android.app.admin.SystemUpdatePolicy
+android.app.appsearch.AppSearchManagerFrameworkInitializer
android.app.assist.AssistContent$1
android.app.assist.AssistContent
android.app.assist.AssistStructure$1
diff --git a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
index 61c5dac..3db0b26 100644
--- a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
+++ b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
@@ -18,7 +18,6 @@
import static android.content.pm.PackageManager.FEATURE_FINGERPRINT;
-import android.accessibilityservice.AccessibilityButtonController.AccessibilityButtonCallback;
import android.annotation.IntDef;
import android.annotation.IntRange;
import android.annotation.UnsupportedAppUsage;
@@ -333,14 +332,6 @@
*/
public static final int FLAG_REQUEST_SHORTCUT_WARNING_DIALOG_SPOKEN_FEEDBACK = 0x00000400;
- /**
- * This flag indicates that the accessibility service will handle the shortcut action itself.
- * A callback {@link AccessibilityButtonCallback#onClicked(AccessibilityButtonController)} is
- * called when the user presses the accessibility shortcut. Otherwise, the service is enabled
- * or disabled by the system instead.
- */
- public static final int FLAG_HANDLE_SHORTCUT = 0x00000800;
-
/** {@hide} */
public static final int FLAG_FORCE_DIRECT_BOOT_AWARE = 0x00010000;
@@ -448,7 +439,6 @@
* @see #FLAG_ENABLE_ACCESSIBILITY_VOLUME
* @see #FLAG_REQUEST_ACCESSIBILITY_BUTTON
* @see #FLAG_REQUEST_SHORTCUT_WARNING_DIALOG_SPOKEN_FEEDBACK
- * @see #FLAG_HANDLE_SHORTCUT
*/
public int flags;
@@ -680,9 +670,8 @@
}
try {
if (platformCompat != null) {
- return platformCompat.isChangeEnabledByPackageName(
- REQUEST_ACCESSIBILITY_BUTTON_CHANGE, mResolveInfo.serviceInfo.packageName,
- mResolveInfo.serviceInfo.applicationInfo.uid);
+ return platformCompat.isChangeEnabled(REQUEST_ACCESSIBILITY_BUTTON_CHANGE,
+ mResolveInfo.serviceInfo.applicationInfo);
}
} catch (RemoteException ignore) {
}
@@ -1163,8 +1152,6 @@
return "FLAG_REQUEST_FINGERPRINT_GESTURES";
case FLAG_REQUEST_SHORTCUT_WARNING_DIALOG_SPOKEN_FEEDBACK:
return "FLAG_REQUEST_SHORTCUT_WARNING_DIALOG_SPOKEN_FEEDBACK";
- case FLAG_HANDLE_SHORTCUT:
- return "FLAG_HANDLE_SHORTCUT";
default:
return null;
}
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index afb7871..5032f77 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -1213,7 +1213,6 @@
OP_START_FOREGROUND,
OP_SMS_FINANCIAL_TRANSACTIONS,
OP_MANAGE_IPSEC_TUNNELS,
- OP_GET_USAGE_STATS,
OP_INSTANT_APP_START_FOREGROUND
};
diff --git a/core/java/android/app/ExpandableListActivity.java b/core/java/android/app/ExpandableListActivity.java
index e08f25a..22de878 100644
--- a/core/java/android/app/ExpandableListActivity.java
+++ b/core/java/android/app/ExpandableListActivity.java
@@ -150,7 +150,11 @@
*
* @see #setListAdapter
* @see android.widget.ExpandableListView
+ *
+ * @deprecated Use {@link androidx.recyclerview.widget.RecyclerView} or use
+ * {@link android.widget.ExpandableListView} directly
*/
+@Deprecated
public class ExpandableListActivity extends Activity implements
OnCreateContextMenuListener,
ExpandableListView.OnChildClickListener, ExpandableListView.OnGroupCollapseListener,
diff --git a/core/java/android/app/ISearchManager.aidl b/core/java/android/app/ISearchManager.aidl
index 53f1a46..0119707 100644
--- a/core/java/android/app/ISearchManager.aidl
+++ b/core/java/android/app/ISearchManager.aidl
@@ -31,6 +31,5 @@
@UnsupportedAppUsage
ComponentName getGlobalSearchActivity();
ComponentName getWebSearchActivity();
- void launchAssist(in Bundle args);
- boolean launchLegacyAssist(String hint, int userHandle, in Bundle args);
+ void launchAssist(int userHandle, in Bundle args);
}
diff --git a/core/java/android/app/LauncherActivity.java b/core/java/android/app/LauncherActivity.java
index 88e2356..b495b3c 100644
--- a/core/java/android/app/LauncherActivity.java
+++ b/core/java/android/app/LauncherActivity.java
@@ -53,7 +53,11 @@
* Displays a list of all activities which can be performed
* for a given intent. Launches when clicked.
*
+ * @deprecated Applications can implement this UI themselves using
+ * {@link androidx.recyclerview.widget.RecyclerView} and
+ * {@link android.content.pm.PackageManager#queryIntentActivities(Intent, int)}
*/
+@Deprecated
public abstract class LauncherActivity extends ListActivity {
Intent mIntent;
PackageManager mPackageManager;
diff --git a/core/java/android/app/ListActivity.java b/core/java/android/app/ListActivity.java
index 2162521..810cca2 100644
--- a/core/java/android/app/ListActivity.java
+++ b/core/java/android/app/ListActivity.java
@@ -171,7 +171,11 @@
*
* @see #setListAdapter
* @see android.widget.ListView
+ *
+ * @deprecated Use {@link androidx.fragment.app.ListFragment} or
+ * {@link androidx.recyclerview.widget.RecyclerView} to implement your Activity instead.
*/
+@Deprecated
public class ListActivity extends Activity {
/**
* This field should be made private, so it is hidden from the SDK.
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index fce7449..b37cc26 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -627,6 +627,13 @@
*/
public static final int FLAG_BUBBLE = 0x00001000;
+ /** @hide */
+ @IntDef({FLAG_SHOW_LIGHTS, FLAG_ONGOING_EVENT, FLAG_INSISTENT, FLAG_ONLY_ALERT_ONCE,
+ FLAG_AUTO_CANCEL, FLAG_NO_CLEAR, FLAG_FOREGROUND_SERVICE, FLAG_HIGH_PRIORITY,
+ FLAG_LOCAL_ONLY, FLAG_GROUP_SUMMARY, FLAG_AUTOGROUP_SUMMARY, FLAG_BUBBLE})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface NotificationFlags{};
+
public int flags;
/** @hide */
@@ -4545,10 +4552,15 @@
}
/**
- * @hide
+ * Set the value for a notification flag
+ *
+ * @param mask Bit mask of the flag
+ * @param value Status (on/off) of the flag
+ *
+ * @return The same Builder.
*/
@NonNull
- public Builder setFlag(int mask, boolean value) {
+ public Builder setFlag(@NotificationFlags int mask, boolean value) {
if (value) {
mN.flags |= mask;
} else {
@@ -10410,6 +10422,16 @@
p.recycle();
return brv;
}
+
+ /**
+ * Override and return true, since {@link RemoteViews#onLoadClass(Class)} is not overridden.
+ *
+ * @see RemoteViews#shouldUseStaticFilter()
+ */
+ @Override
+ protected boolean shouldUseStaticFilter() {
+ return true;
+ }
}
/**
diff --git a/core/java/android/app/SearchManager.java b/core/java/android/app/SearchManager.java
index acca6fc..b10c3e2 100644
--- a/core/java/android/app/SearchManager.java
+++ b/core/java/android/app/SearchManager.java
@@ -16,6 +16,8 @@
package android.app;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.annotation.UnsupportedAppUsage;
import android.content.ActivityNotFoundException;
@@ -973,37 +975,22 @@
}
/**
- * Starts the assistant.
+ * Starts the {@link android.provider.Settings.Secure#ASSISTANT assistant}.
*
- * @param args the args to pass to the assistant
+ * @param args a {@code Bundle} that will be passed to the assistant's
+ * {@link android.service.voice.VoiceInteractionSession#onShow VoiceInteractionSession}
+ * (or as {@link Intent#getExtras() extras} along
+ * {@link Intent#ACTION_ASSIST ACTION_ASSIST} for legacy assistants)
*
* @hide
*/
- @UnsupportedAppUsage
- public void launchAssist(Bundle args) {
+ @SystemApi
+ public void launchAssist(@Nullable Bundle args) {
try {
if (mService == null) {
return;
}
- mService.launchAssist(args);
- } catch (RemoteException re) {
- throw re.rethrowFromSystemServer();
- }
- }
-
- /**
- * Starts the legacy assistant (i.e. the {@link Intent#ACTION_ASSIST}).
- *
- * @param args the args to pass to the assistant
- *
- * @hide
- */
- public boolean launchLegacyAssist(String hint, int userHandle, Bundle args) {
- try {
- if (mService == null) {
- return false;
- }
- return mService.launchLegacyAssist(hint, userHandle, args);
+ mService.launchAssist(mContext.getUserId(), args);
} catch (RemoteException re) {
throw re.rethrowFromSystemServer();
}
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index d40261f..0bfd2c6 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -22,6 +22,7 @@
import android.app.ContextImpl.ServiceInitializationState;
import android.app.admin.DevicePolicyManager;
import android.app.admin.IDevicePolicyManager;
+import android.app.appsearch.AppSearchManagerFrameworkInitializer;
import android.app.blob.BlobStoreManagerFrameworkInitializer;
import android.app.contentsuggestions.ContentSuggestionsManager;
import android.app.contentsuggestions.IContentSuggestionsManager;
@@ -115,16 +116,7 @@
import android.net.lowpan.LowpanManager;
import android.net.nsd.INsdManager;
import android.net.nsd.NsdManager;
-import android.net.wifi.IWifiScanner;
-import android.net.wifi.RttManager;
-import android.net.wifi.WifiManager;
-import android.net.wifi.WifiScanner;
-import android.net.wifi.aware.IWifiAwareManager;
-import android.net.wifi.aware.WifiAwareManager;
-import android.net.wifi.p2p.IWifiP2pManager;
-import android.net.wifi.p2p.WifiP2pManager;
-import android.net.wifi.rtt.IWifiRttManager;
-import android.net.wifi.rtt.WifiRttManager;
+import android.net.wifi.WifiFrameworkInitializer;
import android.nfc.NfcManager;
import android.os.BatteryManager;
import android.os.BatteryStats;
@@ -690,66 +682,6 @@
ConnectivityThread.getInstanceLooper());
}});
- registerService(Context.WIFI_SERVICE, WifiManager.class,
- new CachedServiceFetcher<WifiManager>() {
- @Override
- public WifiManager createService(ContextImpl ctx) {
- return new WifiManager(ctx.getOuterContext(),
- ConnectivityThread.getInstanceLooper());
- }});
-
- registerService(Context.WIFI_P2P_SERVICE, WifiP2pManager.class,
- new StaticServiceFetcher<WifiP2pManager>() {
- @Override
- public WifiP2pManager createService() throws ServiceNotFoundException {
- IBinder b = ServiceManager.getServiceOrThrow(Context.WIFI_P2P_SERVICE);
- IWifiP2pManager service = IWifiP2pManager.Stub.asInterface(b);
- return new WifiP2pManager(service);
- }});
-
- registerService(Context.WIFI_AWARE_SERVICE, WifiAwareManager.class,
- new CachedServiceFetcher<WifiAwareManager>() {
- @Override
- public WifiAwareManager createService(ContextImpl ctx) throws ServiceNotFoundException {
- IBinder b = ServiceManager.getServiceOrThrow(Context.WIFI_AWARE_SERVICE);
- IWifiAwareManager service = IWifiAwareManager.Stub.asInterface(b);
- if (service == null) {
- return null;
- }
- return new WifiAwareManager(ctx.getOuterContext(), service);
- }});
-
- registerService(Context.WIFI_SCANNING_SERVICE, WifiScanner.class,
- new CachedServiceFetcher<WifiScanner>() {
- @Override
- public WifiScanner createService(ContextImpl ctx) throws ServiceNotFoundException {
- IBinder b = ServiceManager.getServiceOrThrow(Context.WIFI_SCANNING_SERVICE);
- IWifiScanner service = IWifiScanner.Stub.asInterface(b);
- return new WifiScanner(ctx.getOuterContext(), service,
- ConnectivityThread.getInstanceLooper());
- }});
-
- registerService(Context.WIFI_RTT_SERVICE, RttManager.class,
- new CachedServiceFetcher<RttManager>() {
- @Override
- public RttManager createService(ContextImpl ctx) throws ServiceNotFoundException {
- IBinder b = ServiceManager.getServiceOrThrow(Context.WIFI_RTT_RANGING_SERVICE);
- IWifiRttManager service = IWifiRttManager.Stub.asInterface(b);
- return new RttManager(ctx.getOuterContext(),
- new WifiRttManager(ctx.getOuterContext(), service));
- }});
-
- registerService(Context.WIFI_RTT_RANGING_SERVICE, WifiRttManager.class,
- new CachedServiceFetcher<WifiRttManager>() {
- @Override
- public WifiRttManager createService(ContextImpl ctx)
- throws ServiceNotFoundException {
- IBinder b = ServiceManager.getServiceOrThrow(
- Context.WIFI_RTT_RANGING_SERVICE);
- IWifiRttManager service = IWifiRttManager.Stub.asInterface(b);
- return new WifiRttManager(ctx.getOuterContext(), service);
- }});
-
registerService(Context.ETHERNET_SERVICE, EthernetManager.class,
new CachedServiceFetcher<EthernetManager>() {
@Override
@@ -1263,6 +1195,8 @@
JobSchedulerFrameworkInitializer.registerServiceWrappers();
BlobStoreManagerFrameworkInitializer.initialize();
TelephonyFrameworkInitializer.registerServiceWrappers();
+ AppSearchManagerFrameworkInitializer.initialize();
+ WifiFrameworkInitializer.registerServiceWrappers();
} finally {
// If any of the above code throws, we're in a pretty bad shape and the process
// will likely crash, but we'll reset it just in case there's an exception handler...
diff --git a/core/java/android/bluetooth/BluetoothPan.java b/core/java/android/bluetooth/BluetoothPan.java
index cfb363a08..4e97627 100644
--- a/core/java/android/bluetooth/BluetoothPan.java
+++ b/core/java/android/bluetooth/BluetoothPan.java
@@ -16,8 +16,13 @@
package android.bluetooth;
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
+import android.annotation.SuppressLint;
+import android.annotation.SystemApi;
import android.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.os.Binder;
@@ -25,6 +30,8 @@
import android.os.RemoteException;
import android.util.Log;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.List;
@@ -40,6 +47,7 @@
*
* @hide
*/
+@SystemApi
public final class BluetoothPan implements BluetoothProfile {
private static final String TAG = "BluetoothPan";
private static final boolean DBG = true;
@@ -67,6 +75,7 @@
* <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission to
* receive.
*/
+ @SuppressLint("ActionValue")
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String ACTION_CONNECTION_STATE_CHANGED =
"android.bluetooth.pan.profile.action.CONNECTION_STATE_CHANGED";
@@ -76,19 +85,32 @@
* The local role of the PAN profile that the remote device is bound to.
* It can be one of {@link #LOCAL_NAP_ROLE} or {@link #LOCAL_PANU_ROLE}.
*/
+ @SuppressLint("ActionValue")
public static final String EXTRA_LOCAL_ROLE = "android.bluetooth.pan.extra.LOCAL_ROLE";
+ /** @hide */
+ @IntDef({PAN_ROLE_NONE, LOCAL_NAP_ROLE, LOCAL_PANU_ROLE})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface LocalPanRole {}
+
public static final int PAN_ROLE_NONE = 0;
/**
* The local device is acting as a Network Access Point.
*/
public static final int LOCAL_NAP_ROLE = 1;
- public static final int REMOTE_NAP_ROLE = 1;
/**
* The local device is acting as a PAN User.
*/
public static final int LOCAL_PANU_ROLE = 2;
+
+ /** @hide */
+ @IntDef({PAN_ROLE_NONE, REMOTE_NAP_ROLE, REMOTE_PANU_ROLE})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface RemotePanRole {}
+
+ public static final int REMOTE_NAP_ROLE = 1;
+
public static final int REMOTE_PANU_ROLE = 2;
/**
@@ -134,6 +156,8 @@
/**
* Create a BluetoothPan proxy object for interacting with the local
* Bluetooth Service which handles the Pan profile
+ *
+ * @hide
*/
@UnsupportedAppUsage
/*package*/ BluetoothPan(Context context, ServiceListener listener) {
@@ -235,7 +259,7 @@
* {@inheritDoc}
*/
@Override
- public List<BluetoothDevice> getConnectedDevices() {
+ public @NonNull List<BluetoothDevice> getConnectedDevices() {
if (VDBG) log("getConnectedDevices()");
final IBluetoothPan service = getService();
if (service != null && isEnabled()) {
@@ -252,6 +276,7 @@
/**
* {@inheritDoc}
+ * @hide
*/
@Override
public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
@@ -273,7 +298,7 @@
* {@inheritDoc}
*/
@Override
- public int getConnectionState(BluetoothDevice device) {
+ public int getConnectionState(@Nullable BluetoothDevice device) {
if (VDBG) log("getState(" + device + ")");
final IBluetoothPan service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
@@ -288,7 +313,11 @@
return BluetoothProfile.STATE_DISCONNECTED;
}
- @UnsupportedAppUsage
+ /**
+ * Turns on/off bluetooth tethering
+ *
+ * @param value is whether to enable or disable bluetooth tethering
+ */
public void setBluetoothTethering(boolean value) {
String pkgName = mContext.getOpPackageName();
if (DBG) log("setBluetoothTethering(" + value + "), calling package:" + pkgName);
@@ -302,7 +331,11 @@
}
}
- @UnsupportedAppUsage
+ /**
+ * Determines whether tethering is enabled
+ *
+ * @return true if tethering is on, false if not or some error occurred
+ */
public boolean isTetheringOn() {
if (VDBG) log("isTetheringOn()");
final IBluetoothPan service = getService();
diff --git a/core/java/android/bluetooth/BluetoothProfile.java b/core/java/android/bluetooth/BluetoothProfile.java
index f5aa014..f1ac765 100644
--- a/core/java/android/bluetooth/BluetoothProfile.java
+++ b/core/java/android/bluetooth/BluetoothProfile.java
@@ -20,9 +20,9 @@
import android.Manifest;
import android.annotation.IntDef;
import android.annotation.RequiresPermission;
+import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.annotation.UnsupportedAppUsage;
-import android.os.Build;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -43,6 +43,7 @@
* This extra represents the current connection state of the profile of the
* Bluetooth device.
*/
+ @SuppressLint("ActionValue")
String EXTRA_STATE = "android.bluetooth.profile.extra.STATE";
/**
@@ -51,6 +52,7 @@
* This extra represents the previous connection state of the profile of the
* Bluetooth device.
*/
+ @SuppressLint("ActionValue")
String EXTRA_PREVIOUS_STATE =
"android.bluetooth.profile.extra.PREVIOUS_STATE";
@@ -106,7 +108,7 @@
*
* @hide
*/
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
+ @SystemApi
int PAN = 5;
/**
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 7703e08..0fdb513 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -3335,6 +3335,7 @@
ROLLBACK_SERVICE,
DROPBOX_SERVICE,
//@hide: DEVICE_IDLE_CONTROLLER,
+ //@hide: POWER_WHITELIST_MANAGER,
DEVICE_POLICY_SERVICE,
UI_MODE_SERVICE,
DOWNLOAD_SERVICE,
@@ -4345,6 +4346,15 @@
public static final String DEVICE_IDLE_CONTROLLER = "deviceidle";
/**
+ * System service name for the PowerWhitelistManager.
+ *
+ * @see #getSystemService(String)
+ * @hide
+ */
+ @TestApi
+ public static final String POWER_WHITELIST_MANAGER = "power_whitelist";
+
+ /**
* Use with {@link #getSystemService(String)} to retrieve a
* {@link android.app.admin.DevicePolicyManager} for working with global
* device policy management.
@@ -4898,6 +4908,15 @@
public static final String BATTERY_STATS_SERVICE = "batterystats";
/**
+ * Use with {@link #getSystemService(String)} to retrieve an
+ * AppSearchManager for indexing and querying app data managed
+ * by the system.
+ *
+ * @see #getSystemService(String)
+ */
+ public static final String APP_SEARCH_SERVICE = "app_search";
+
+ /**
* Determine whether the given permission is allowed for a particular
* process and user ID running in the system.
*
diff --git a/core/java/android/content/res/AssetManager.java b/core/java/android/content/res/AssetManager.java
index 2d9ca67..168eae6 100644
--- a/core/java/android/content/res/AssetManager.java
+++ b/core/java/android/content/res/AssetManager.java
@@ -206,7 +206,7 @@
@VisibleForTesting
public static void createSystemAssetsInZygoteLocked(boolean reinitialize,
String frameworkPath) {
- if (sSystem != null || reinitialize) {
+ if (sSystem != null && !reinitialize) {
return;
}
@@ -225,7 +225,9 @@
sSystemApkAssetsSet = new ArraySet<>(apkAssets);
sSystemApkAssets = apkAssets.toArray(new ApkAssets[apkAssets.size()]);
- sSystem = new AssetManager(true /*sentinel*/);
+ if (sSystem == null) {
+ sSystem = new AssetManager(true /*sentinel*/);
+ }
sSystem.setApkAssets(sSystemApkAssets, false /*invalidateCaches*/);
} catch (IOException e) {
throw new IllegalStateException("Failed to create system AssetManager", e);
diff --git a/core/java/android/net/IpConfiguration.java b/core/java/android/net/IpConfiguration.java
index 2af82d7..143467b 100644
--- a/core/java/android/net/IpConfiguration.java
+++ b/core/java/android/net/IpConfiguration.java
@@ -16,6 +16,10 @@
package android.net;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SuppressLint;
+import android.annotation.SystemApi;
import android.annotation.UnsupportedAppUsage;
import android.net.StaticIpConfiguration;
import android.os.Parcel;
@@ -27,13 +31,17 @@
* A class representing a configured network.
* @hide
*/
-public class IpConfiguration implements Parcelable {
+@SystemApi
+public final class IpConfiguration implements Parcelable {
private static final String TAG = "IpConfiguration";
+ // This enum has been used by apps through reflection for many releases.
+ // Therefore they can't just be removed. Duplicating these constants to
+ // give an alternate SystemApi is a worse option than exposing them.
+ @SuppressLint("Enum")
public enum IpAssignment {
/* Use statically configured IP settings. Configuration can be accessed
* with staticIpConfiguration */
- @UnsupportedAppUsage
STATIC,
/* Use dynamically configured IP settings */
DHCP,
@@ -42,14 +50,19 @@
UNASSIGNED
}
+ /** @hide */
public IpAssignment ipAssignment;
+ /** @hide */
public StaticIpConfiguration staticIpConfiguration;
+ // This enum has been used by apps through reflection for many releases.
+ // Therefore they can't just be removed. Duplicating these constants to
+ // give an alternate SystemApi is a worse option than exposing them.
+ @SuppressLint("Enum")
public enum ProxySettings {
/* No proxy is to be used. Any existing proxy settings
* should be cleared. */
- @UnsupportedAppUsage
NONE,
/* Use statically configured proxy. Configuration can be accessed
* with httpProxy. */
@@ -62,8 +75,10 @@
PAC
}
+ /** @hide */
public ProxySettings proxySettings;
+ /** @hide */
@UnsupportedAppUsage
public ProxyInfo httpProxy;
@@ -83,6 +98,7 @@
init(IpAssignment.UNASSIGNED, ProxySettings.UNASSIGNED, null, null);
}
+ /** @hide */
@UnsupportedAppUsage
public IpConfiguration(IpAssignment ipAssignment,
ProxySettings proxySettings,
@@ -91,7 +107,7 @@
init(ipAssignment, proxySettings, staticIpConfiguration, httpProxy);
}
- public IpConfiguration(IpConfiguration source) {
+ public IpConfiguration(@NonNull IpConfiguration source) {
this();
if (source != null) {
init(source.ipAssignment, source.proxySettings,
@@ -99,35 +115,35 @@
}
}
- public IpAssignment getIpAssignment() {
+ public @NonNull IpAssignment getIpAssignment() {
return ipAssignment;
}
- public void setIpAssignment(IpAssignment ipAssignment) {
+ public void setIpAssignment(@NonNull IpAssignment ipAssignment) {
this.ipAssignment = ipAssignment;
}
- public StaticIpConfiguration getStaticIpConfiguration() {
+ public @Nullable StaticIpConfiguration getStaticIpConfiguration() {
return staticIpConfiguration;
}
- public void setStaticIpConfiguration(StaticIpConfiguration staticIpConfiguration) {
+ public void setStaticIpConfiguration(@Nullable StaticIpConfiguration staticIpConfiguration) {
this.staticIpConfiguration = staticIpConfiguration;
}
- public ProxySettings getProxySettings() {
+ public @NonNull ProxySettings getProxySettings() {
return proxySettings;
}
- public void setProxySettings(ProxySettings proxySettings) {
+ public void setProxySettings(@NonNull ProxySettings proxySettings) {
this.proxySettings = proxySettings;
}
- public ProxyInfo getHttpProxy() {
+ public @Nullable ProxyInfo getHttpProxy() {
return httpProxy;
}
- public void setHttpProxy(ProxyInfo httpProxy) {
+ public void setHttpProxy(@Nullable ProxyInfo httpProxy) {
this.httpProxy = httpProxy;
}
@@ -175,13 +191,19 @@
83 * httpProxy.hashCode();
}
- /** Implement the Parcelable interface */
+ /**
+ * Implement the Parcelable interface
+ * @hide
+ */
public int describeContents() {
return 0;
}
- /** Implement the Parcelable interface */
- public void writeToParcel(Parcel dest, int flags) {
+ /**
+ * Implement the Parcelable interface
+ * @hide
+ */
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeString(ipAssignment.name());
dest.writeString(proxySettings.name());
dest.writeParcelable(staticIpConfiguration, flags);
@@ -189,7 +211,7 @@
}
/** Implement the Parcelable interface */
- public static final @android.annotation.NonNull Creator<IpConfiguration> CREATOR =
+ public static final @NonNull Creator<IpConfiguration> CREATOR =
new Creator<IpConfiguration>() {
public IpConfiguration createFromParcel(Parcel in) {
IpConfiguration config = new IpConfiguration();
diff --git a/core/java/android/net/NetworkKey.java b/core/java/android/net/NetworkKey.java
index 4254240..47c08a4 100644
--- a/core/java/android/net/NetworkKey.java
+++ b/core/java/android/net/NetworkKey.java
@@ -16,6 +16,7 @@
package android.net;
+import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
@@ -27,6 +28,8 @@
import android.text.TextUtils;
import android.util.Log;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.util.Objects;
/**
@@ -48,6 +51,13 @@
/** A wifi network, for which {@link #wifiKey} will be populated. */
public static final int TYPE_WIFI = 1;
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = {"TYPE_"}, value = {
+ TYPE_WIFI
+ })
+ public @interface NetworkType {}
+
/**
* The type of this network.
* @see #TYPE_WIFI
@@ -65,7 +75,6 @@
*
* @return A new {@link NetworkKey} instance or <code>null</code> if the given
* {@link ScanResult} instance is malformed.
- * @hide
*/
@Nullable
public static NetworkKey createFromScanResult(@Nullable ScanResult result) {
diff --git a/core/java/android/net/NetworkScore.java b/core/java/android/net/NetworkScore.java
index 1ab6335..13f2994 100644
--- a/core/java/android/net/NetworkScore.java
+++ b/core/java/android/net/NetworkScore.java
@@ -154,4 +154,9 @@
}
return true;
}
+
+ /** Convert to a string */
+ public String toString() {
+ return "NetworkScore[" + mExtensions.toString() + "]";
+ }
}
diff --git a/core/java/android/net/NetworkScoreManager.java b/core/java/android/net/NetworkScoreManager.java
index 50dd468..f6dc525 100644
--- a/core/java/android/net/NetworkScoreManager.java
+++ b/core/java/android/net/NetworkScoreManager.java
@@ -17,7 +17,9 @@
package android.net;
import android.Manifest.permission;
+import android.annotation.CallbackExecutor;
import android.annotation.IntDef;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
@@ -25,13 +27,16 @@
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.content.Context;
+import android.os.Binder;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.ServiceManager.ServiceNotFoundException;
+import android.util.Log;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.List;
+import java.util.concurrent.Executor;
/**
* Class that manages communication between network subsystems and a network scorer.
@@ -50,19 +55,25 @@
@SystemApi
@SystemService(Context.NETWORK_SCORE_SERVICE)
public class NetworkScoreManager {
+ private static final String TAG = "NetworkScoreManager";
+
/**
* Activity action: ask the user to change the active network scorer. This will show a dialog
* that asks the user whether they want to replace the current active scorer with the one
* specified in {@link #EXTRA_PACKAGE_NAME}. The activity will finish with RESULT_OK if the
* active scorer was changed or RESULT_CANCELED if it failed for any reason.
+ * @deprecated No longer sent.
*/
+ @Deprecated
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
public static final String ACTION_CHANGE_ACTIVE = "android.net.scoring.CHANGE_ACTIVE";
/**
* Extra used with {@link #ACTION_CHANGE_ACTIVE} to specify the new scorer package. Set with
* {@link android.content.Intent#putExtra(String, String)}.
+ * @deprecated No longer sent.
*/
+ @Deprecated
public static final String EXTRA_PACKAGE_NAME = "packageName";
/**
@@ -73,7 +84,9 @@
* configured by the user as well as any open networks.
*
* <p class="note">This is a protected intent that can only be sent by the system.
+ * @deprecated Use {@link #ACTION_RECOMMEND_NETWORKS} to bind scorer app instead.
*/
+ @Deprecated
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String ACTION_SCORE_NETWORKS = "android.net.scoring.SCORE_NETWORKS";
@@ -81,7 +94,9 @@
* Extra used with {@link #ACTION_SCORE_NETWORKS} to specify the networks to be scored, as an
* array of {@link NetworkKey}s. Can be obtained with
* {@link android.content.Intent#getParcelableArrayExtra(String)}}.
+ * @deprecated Use {@link #ACTION_RECOMMEND_NETWORKS} to bind scorer app instead.
*/
+ @Deprecated
public static final String EXTRA_NETWORKS_TO_SCORE = "networksToScore";
/**
@@ -285,7 +300,7 @@
* @throws SecurityException if the caller is not the active scorer.
*/
@RequiresPermission(android.Manifest.permission.SCORE_NETWORKS)
- public boolean updateScores(ScoredNetwork[] networks) throws SecurityException {
+ public boolean updateScores(@NonNull ScoredNetwork[] networks) throws SecurityException {
try {
return mService.updateScores(networks);
} catch (RemoteException e) {
@@ -359,13 +374,21 @@
/**
* Request scoring for networks.
*
- * @return true if the broadcast was sent, or false if there is no active scorer.
+ * <p>
+ * Note: The results (i.e scores) for these networks, when available will be provided via the
+ * callback registered with {@link #registerNetworkScoreCallback(int, int, Executor,
+ * NetworkScoreCallback)}. The calling module is responsible for registering a callback to
+ * receive the results before requesting new scores via this API.
+ *
+ * @return true if the request was successfully sent, or false if there is no active scorer.
* @throws SecurityException if the caller does not hold the
* {@link permission#REQUEST_NETWORK_SCORES} permission.
+ *
* @hide
*/
+ @SystemApi
@RequiresPermission(android.Manifest.permission.REQUEST_NETWORK_SCORES)
- public boolean requestScores(NetworkKey[] networks) throws SecurityException {
+ public boolean requestScores(@NonNull NetworkKey[] networks) throws SecurityException {
try {
return mService.requestScores(networks);
} catch (RemoteException e) {
@@ -431,6 +454,88 @@
}
/**
+ * Base class for network score cache callback. Should be extended by applications and set
+ * when calling {@link #registerNetworkScoreCallback(int, int, NetworkScoreCallback,
+ * Executor)}
+ *
+ * @hide
+ */
+ @SystemApi
+ public interface NetworkScoreCallback {
+ /**
+ * Called when a new set of network scores are available.
+ * This is triggered in response when the client invokes
+ * {@link #requestScores(NetworkKey[])} to score a new set of networks.
+ *
+ * @param networks List of {@link ScoredNetwork} containing updated scores.
+ */
+ void updateScores(@NonNull List<ScoredNetwork> networks);
+
+ /**
+ * Invokes when all the previously provided scores are no longer valid.
+ */
+ void clearScores();
+ }
+
+ /**
+ * Callback proxy for {@link NetworkScoreCallback} objects.
+ */
+ private class NetworkScoreCallbackProxy extends INetworkScoreCache.Stub {
+ private final Executor mExecutor;
+ private final NetworkScoreCallback mCallback;
+
+ NetworkScoreCallbackProxy(Executor executor, NetworkScoreCallback callback) {
+ mExecutor = executor;
+ mCallback = callback;
+ }
+
+ @Override
+ public void updateScores(@NonNull List<ScoredNetwork> networks) {
+ Binder.clearCallingIdentity();
+ mExecutor.execute(() -> {
+ mCallback.updateScores(networks);
+ });
+ }
+
+ @Override
+ public void clearScores() {
+ Binder.clearCallingIdentity();
+ mExecutor.execute(() -> {
+ mCallback.clearScores();
+ });
+ }
+ }
+
+ /**
+ * Register a network score callback.
+ *
+ * @param networkType the type of network this cache can handle. See {@link NetworkKey#type}
+ * @param filterType the {@link CacheUpdateFilter} to apply
+ * @param callback implementation of {@link NetworkScoreCallback} that will be invoked when the
+ * scores change.
+ * @param executor The executor on which to execute the callbacks.
+ * @throws SecurityException if the caller does not hold the
+ * {@link permission#REQUEST_NETWORK_SCORES} permission.
+ * @throws IllegalArgumentException if a callback is already registered for this type.
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.REQUEST_NETWORK_SCORES)
+ public void registerNetworkScoreCallback(@NetworkKey.NetworkType int networkType,
+ @CacheUpdateFilter int filterType,
+ @NonNull @CallbackExecutor Executor executor,
+ @NonNull NetworkScoreCallback callback) throws SecurityException {
+ if (callback == null || executor == null) {
+ throw new IllegalArgumentException("callback / executor cannot be null");
+ }
+ Log.v(TAG, "registerNetworkScoreCallback: callback=" + callback + ", executor="
+ + executor);
+ // Use the @hide method.
+ registerNetworkScoreCache(
+ networkType, new NetworkScoreCallbackProxy(executor, callback), filterType);
+ }
+
+ /**
* Determine whether the application with the given UID is the enabled scorer.
*
* @param callingUid the UID to check
diff --git a/core/java/android/net/ProxyInfo.java b/core/java/android/net/ProxyInfo.java
index 807c467..9d92db4 100644
--- a/core/java/android/net/ProxyInfo.java
+++ b/core/java/android/net/ProxyInfo.java
@@ -16,7 +16,8 @@
package android.net;
-
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
@@ -89,6 +90,15 @@
}
/**
+ * Construct a {@link ProxyInfo} object that will download and run the PAC script at the
+ * specified URL and port.
+ */
+ @NonNull
+ public static ProxyInfo buildPacProxy(@NonNull Uri pacUrl, int port) {
+ return new ProxyInfo(pacUrl, port);
+ }
+
+ /**
* Create a ProxyProperties that points at a HTTP Proxy.
* @hide
*/
@@ -105,7 +115,7 @@
* Create a ProxyProperties that points at a PAC URL.
* @hide
*/
- public ProxyInfo(Uri pacFileUrl) {
+ public ProxyInfo(@NonNull Uri pacFileUrl) {
mHost = LOCAL_HOST;
mPort = LOCAL_PORT;
mExclusionList = LOCAL_EXCL_LIST;
@@ -132,7 +142,7 @@
* Only used in PacManager after Local Proxy is bound.
* @hide
*/
- public ProxyInfo(Uri pacFileUrl, int localProxyPort) {
+ public ProxyInfo(@NonNull Uri pacFileUrl, int localProxyPort) {
mHost = LOCAL_HOST;
mPort = localProxyPort;
mExclusionList = LOCAL_EXCL_LIST;
@@ -159,11 +169,10 @@
mPacFileUrl = Uri.EMPTY;
}
- // copy constructor instead of clone
/**
- * @hide
+ * A copy constructor to hold proxy properties.
*/
- public ProxyInfo(ProxyInfo source) {
+ public ProxyInfo(@Nullable ProxyInfo source) {
if (source != null) {
mHost = source.getHost();
mPort = source.getPort();
@@ -226,12 +235,13 @@
* comma separated
* @hide
*/
+ @Nullable
public String getExclusionListAsString() {
return mExclusionList;
}
/**
- * @hide
+ * Return true if the pattern of proxy is valid, otherwise return false.
*/
public boolean isValid() {
if (!Uri.EMPTY.equals(mPacFileUrl)) return true;
diff --git a/core/java/android/os/FileUtils.java b/core/java/android/os/FileUtils.java
index f789b72..2ac3def 100644
--- a/core/java/android/os/FileUtils.java
+++ b/core/java/android/os/FileUtils.java
@@ -1275,7 +1275,13 @@
/**
* Closes the given object quietly, ignoring any checked exceptions. Does
* nothing if the given object is {@code null}.
+ *
+ * @deprecated This method may suppress potentially significant exceptions, particularly when
+ * closing writable resources. With a writable resource, a failure thrown from {@code close()}
+ * should be considered as significant as a failure thrown from a write method because it may
+ * indicate a failure to flush bytes to the underlying resource.
*/
+ @Deprecated
public static void closeQuietly(@Nullable AutoCloseable closeable) {
IoUtils.closeQuietly(closeable);
}
@@ -1283,7 +1289,13 @@
/**
* Closes the given object quietly, ignoring any checked exceptions. Does
* nothing if the given object is {@code null}.
+ *
+ * @deprecated This method may suppress potentially significant exceptions, particularly when
+ * closing writable resources. With a writable resource, a failure thrown from {@code close()}
+ * should be considered as significant as a failure thrown from a write method because it may
+ * indicate a failure to flush bytes to the underlying resource.
*/
+ @Deprecated
public static void closeQuietly(@Nullable FileDescriptor fd) {
IoUtils.closeQuietly(fd);
}
diff --git a/core/java/android/os/HidlMemory.java b/core/java/android/os/HidlMemory.java
new file mode 100644
index 0000000..aeb6589
--- /dev/null
+++ b/core/java/android/os/HidlMemory.java
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os;
+
+import android.annotation.IntRange;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.annotation.TestApi;
+
+import java.io.Closeable;
+import java.io.IOException;
+
+/**
+ * An abstract representation of a memory block, as representing by the HIDL system.
+ *
+ * The block is defined by a {name, size, handle} tuple, where the name is used to determine how to
+ * interpret the handle. The underlying handle is assumed to be owned by this instance and will be
+ * closed as soon as {@link #close()} is called on this instance, or this instance has been
+ * finalized (the latter supports using it in a shared manner without having to worry about who owns
+ * this instance, the former is more efficient resource-wise and is recommended for most use-cases).
+ * Note, however, that ownership of the handle does not necessarily imply ownership of the
+ * underlying file descriptors - the underlying handle may or may not own them. If you want the
+ * underlying handle to outlive this instance, call {@link #releaseHandle()} to obtain the handle
+ * and detach the ownership relationship.
+ *
+ * @hide
+ */
+@SystemApi
+@TestApi
+public class HidlMemory implements Closeable {
+ private final @NonNull String mName;
+ private final long mSize;
+ private @Nullable NativeHandle mHandle;
+ private long mNativeContext; // For use of native code.
+
+ /**
+ * Constructor.
+ *
+ * @param name The name of the IMapper service used to resolve the handle (e.g. "ashmem").
+ * @param size The (non-negative) size in bytes of the memory block.
+ * @param handle The handle. May be null. This instance will own the handle and will close it
+ * as soon as {@link #close()} is called or the object is destroyed. This, this
+ * handle instance should generally not be shared with other clients.
+ */
+ public HidlMemory(@NonNull String name, @IntRange(from = 0) long size,
+ @Nullable NativeHandle handle) {
+ mName = name;
+ mSize = size;
+ mHandle = handle;
+ }
+
+ /**
+ * Create a copy of this instance, where the underlying handle (and its file descriptors) have
+ * been duplicated.
+ */
+ @NonNull
+ public HidlMemory dup() throws IOException {
+ return new HidlMemory(mName, mSize, mHandle != null ? mHandle.dup() : null);
+ }
+
+ /**
+ * Close the underlying native handle. No-op if handle is null or has been released using {@link
+ * #releaseHandle()}.
+ */
+ @Override
+ public void close() throws IOException {
+ if (mHandle != null) {
+ mHandle.close();
+ }
+ }
+
+ /**
+ * Disowns the underlying handle and returns it. This object becomes invalid.
+ *
+ * @return The underlying handle.
+ */
+ @NonNull
+ public NativeHandle releaseHandle() {
+ NativeHandle handle = mHandle;
+ mHandle = null;
+ return handle;
+ }
+
+ /**
+ * Gets the name, which represents how the handle is to be interpreted.
+ *
+ * @return The name.
+ */
+ @NonNull
+ public String getName() {
+ return mName;
+ }
+
+ /**
+ * Gets the size of the block, in bytes.
+ *
+ * @return The size.
+ */
+ public long getSize() {
+ return mSize;
+ }
+
+ /**
+ * Gets a native handle. The actual interpretation depends on the name and is implementation
+ * defined.
+ *
+ * @return The native handle.
+ */
+ @Nullable
+ public NativeHandle getHandle() {
+ return mHandle;
+ }
+
+ @Override
+ protected void finalize() {
+ try {
+ close();
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ } finally {
+ nativeFinalize();
+ }
+ }
+
+ private native void nativeFinalize();
+}
diff --git a/core/java/android/os/HidlMemoryUtil.java b/core/java/android/os/HidlMemoryUtil.java
new file mode 100644
index 0000000..b08822dd
--- /dev/null
+++ b/core/java/android/os/HidlMemoryUtil.java
@@ -0,0 +1,215 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.os;
+
+import static android.system.OsConstants.MAP_SHARED;
+import static android.system.OsConstants.PROT_READ;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SuppressLint;
+import android.annotation.SystemApi;
+import android.annotation.TestApi;
+import android.system.ErrnoException;
+import android.system.Os;
+import android.util.Log;
+
+import com.android.internal.util.Preconditions;
+
+import java.nio.ByteBuffer;
+import java.nio.DirectByteBuffer;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Provides utilities for dealing with HidlMemory.
+ *
+ * @hide
+ */
+public final class HidlMemoryUtil {
+ static private final String TAG = "HidlMemoryUtil";
+
+ private HidlMemoryUtil() {
+ }
+
+ /**
+ * Copies a byte-array into a new Ashmem region and return it as HidlMemory.
+ * The returned instance owns the underlying file descriptors, and the client should generally
+ * call close on it when no longer in use (or otherwise, when the object gets destroyed it will
+ * be closed).
+ *
+ * @param input The input byte array.
+ * @return A HidlMemory instance, containing a copy of the input.
+ */
+ public static @NonNull
+ HidlMemory byteArrayToHidlMemory(@NonNull byte[] input) {
+ return byteArrayToHidlMemory(input, null);
+ }
+
+ /**
+ * Copies a byte-array into a new Ashmem region and return it as HidlMemory.
+ * The returned instance owns the underlying file descriptors, and the client should generally
+ * call close on it when no longer in use (or otherwise, when the object gets destroyed it will
+ * be closed).
+ *
+ * @param input The input byte array.
+ * @param name An optional name for the ashmem region.
+ * @return A HidlMemory instance, containing a copy of the input.
+ */
+ public static @NonNull
+ HidlMemory byteArrayToHidlMemory(@NonNull byte[] input, @Nullable String name) {
+ Preconditions.checkNotNull(input);
+
+ if (input.length == 0) {
+ return new HidlMemory("ashmem", 0, null);
+ }
+
+ try {
+ SharedMemory shmem = SharedMemory.create(name != null ? name : "", input.length);
+ ByteBuffer buffer = shmem.mapReadWrite();
+ buffer.put(input);
+ shmem.unmap(buffer);
+ NativeHandle handle = new NativeHandle(shmem.getFileDescriptor(), true);
+ return new HidlMemory("ashmem", input.length, handle);
+ } catch (ErrnoException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Copies a byte list into a new Ashmem region and return it as HidlMemory.
+ * The returned instance owns the underlying file descriptors, and the client should generally
+ * call close on it when no longer in use (or otherwise, when the object gets destroyed it will
+ * be closed).
+ *
+ * @param input The input byte list.
+ * @return A HidlMemory instance, containing a copy of the input.
+ */
+ public static @NonNull
+ HidlMemory byteListToHidlMemory(@NonNull List<Byte> input) {
+ return byteListToHidlMemory(input, null);
+ }
+
+ /**
+ * Copies a byte list into a new Ashmem region and return it as HidlMemory.
+ * The returned instance owns the underlying file descriptors, and the client should generally
+ * call close on it when no longer in use (or otherwise, when the object gets destroyed it will
+ * be closed).
+ *
+ * @param input The input byte list.
+ * @param name An optional name for the ashmem region.
+ * @return A HidlMemory instance, containing a copy of the input.
+ */
+ public static @NonNull
+ HidlMemory byteListToHidlMemory(@NonNull List<Byte> input, @Nullable String name) {
+ Preconditions.checkNotNull(input);
+
+ if (input.isEmpty()) {
+ return new HidlMemory("ashmem", 0, null);
+ }
+
+ try {
+ SharedMemory shmem = SharedMemory.create(name != null ? name : "", input.size());
+ ByteBuffer buffer = shmem.mapReadWrite();
+ for (Byte b : input) {
+ buffer.put(b);
+ }
+ shmem.unmap(buffer);
+ NativeHandle handle = new NativeHandle(shmem.getFileDescriptor(), true);
+ return new HidlMemory("ashmem", input.size(), handle);
+ } catch (ErrnoException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Copies all data from a HidlMemory instance into a byte array.
+ *
+ * @param mem The HidlMemory instance. Must be of name "ashmem" and of size that doesn't exceed
+ * {@link Integer#MAX_VALUE}.
+ * @return A byte array, containing a copy of the input.
+ */
+ public static @NonNull
+ byte[] hidlMemoryToByteArray(@NonNull HidlMemory mem) {
+ Preconditions.checkNotNull(mem);
+ Preconditions.checkArgumentInRange(mem.getSize(), 0L, (long) Integer.MAX_VALUE,
+ "Memory size");
+ Preconditions.checkArgument(mem.getSize() == 0 || mem.getName().equals("ashmem"),
+ "Unsupported memory type: %s", mem.getName());
+
+ if (mem.getSize() == 0) {
+ return new byte[0];
+ }
+
+ ByteBuffer buffer = getBuffer(mem);
+ byte[] result = new byte[buffer.remaining()];
+ buffer.get(result);
+ return result;
+ }
+
+ /**
+ * Copies all data from a HidlMemory instance into a byte list.
+ *
+ * @param mem The HidlMemory instance. Must be of name "ashmem" and of size that doesn't exceed
+ * {@link Integer#MAX_VALUE}.
+ * @return A byte list, containing a copy of the input.
+ */
+ @SuppressLint("ConcreteCollection")
+ public static @NonNull
+ ArrayList<Byte> hidlMemoryToByteList(@NonNull HidlMemory mem) {
+ Preconditions.checkNotNull(mem);
+ Preconditions.checkArgumentInRange(mem.getSize(), 0L, (long) Integer.MAX_VALUE,
+ "Memory size");
+ Preconditions.checkArgument(mem.getSize() == 0 || mem.getName().equals("ashmem"),
+ "Unsupported memory type: %s", mem.getName());
+
+ if (mem.getSize() == 0) {
+ return new ArrayList<>();
+ }
+
+ ByteBuffer buffer = getBuffer(mem);
+
+ ArrayList<Byte> result = new ArrayList<>(buffer.remaining());
+ while (buffer.hasRemaining()) {
+ result.add(buffer.get());
+ }
+ return result;
+ }
+
+ private static ByteBuffer getBuffer(@NonNull HidlMemory mem) {
+ try {
+ final int size = (int) mem.getSize();
+
+ if (size == 0) {
+ return ByteBuffer.wrap(new byte[0]);
+ }
+
+ NativeHandle handle = mem.getHandle();
+
+ final long address = Os.mmap(0, size, PROT_READ, MAP_SHARED, handle.getFileDescriptor(),
+ 0);
+ return new DirectByteBuffer(size, address, handle.getFileDescriptor(), () -> {
+ try {
+ Os.munmap(address, size);
+ } catch (ErrnoException e) {
+ Log.wtf(TAG, e);
+ }
+ }, true);
+ } catch (ErrnoException e) {
+ throw new RuntimeException(e);
+ }
+ }
+}
diff --git a/core/java/android/os/HwBlob.java b/core/java/android/os/HwBlob.java
index 2c453bf..154227b2 100644
--- a/core/java/android/os/HwBlob.java
+++ b/core/java/android/os/HwBlob.java
@@ -92,6 +92,14 @@
* @throws IndexOutOfBoundsException when offset is out of this HwBlob
*/
public native final String getString(long offset);
+ /**
+ * For embedded fields that follow a two-step approach for reading, first obtain their field
+ * handle using this method, and pass that field handle to the respective
+ * HwParcel.readEmbedded*() method.
+ * @param offset The field offset.
+ * @return The field handle.
+ */
+ public native final long getFieldHandle(long offset);
/**
* Copy the blobs data starting from the given byte offset into the range, copying
@@ -312,6 +320,20 @@
public native final void putBlob(long offset, HwBlob blob);
/**
+ * Writes a HidlMemory instance (without duplicating the underlying file descriptors) at an
+ * offset.
+ *
+ * @param offset location to write value
+ * @param mem a {@link HidlMemory} instance to write
+ * @throws IndexOutOfBoundsException when [offset, offset + sizeof(jobject)] is out of range
+ */
+ public final void putHidlMemory(long offset, @NonNull HidlMemory mem) {
+ putNativeHandle(offset + 0 /* offset of 'handle' field. */, mem.getHandle());
+ putInt64(offset + 16 /* offset of 'size' field. */, mem.getSize());
+ putString(offset + 24 /* offset of 'name' field. */, mem.getName());
+ }
+
+ /**
* @return current handle of HwBlob for reference in a parcelled binder transaction
*/
public native final long handle();
diff --git a/core/java/android/os/HwParcel.java b/core/java/android/os/HwParcel.java
index 5e8929c..9786f16 100644
--- a/core/java/android/os/HwParcel.java
+++ b/core/java/android/os/HwParcel.java
@@ -324,6 +324,15 @@
public native final void writeStrongBinder(IHwBinder binder);
/**
+ * Write a HidlMemory object (without duplicating the underlying file descriptors) to the end
+ * of the parcel.
+ *
+ * @param memory value to write
+ */
+ @FastNative
+ public native final void writeHidlMemory(@NonNull HidlMemory memory);
+
+ /**
* Checks to make sure that the interface name matches the name written by the parcel
* sender by writeInterfaceToken
*
@@ -582,6 +591,38 @@
public native final IHwBinder readStrongBinder();
/**
+ * Reads a HidlMemory value (without duplicating the underlying file
+ * descriptors) from the parcel. These file descriptors will only
+ * be open for the duration that the binder window is open. If they
+ * are needed further, you must call {@link HidlMemory#dup()}, which makes you also
+ * responsible for calling {@link HidlMemory#close()}.
+ *
+ * @return HidlMemory object read from parcel.
+ * @throws IllegalArgumentException if the parcel has no more data or is otherwise corrupt.
+ */
+ @FastNative
+ @NonNull
+ public native final HidlMemory readHidlMemory();
+
+ /**
+ * Reads an embedded HidlMemory (without duplicating the underlying
+ * file descriptors) from the parcel. These file descriptors will only
+ * be open for the duration that the binder window is open. If they
+ * are needed further, you must call {@link HidlMemory#dup()}. You
+ * do not need to call close on the HidlMemory returned from this.
+ *
+ * @param fieldHandle handle of the field, obtained from the {@link HwBlob}.
+ * @param parentHandle parentHandle from which to read the embedded object
+ * @param offset offset into parent
+ * @return a {@link HidlMemory} instance parsed from the parcel
+ * @throws IllegalArgumentException if the parcel has no more data
+ */
+ @FastNative
+ @NonNull
+ public native final @Nullable
+ HidlMemory readEmbeddedHidlMemory(long fieldHandle, long parentHandle, long offset);
+
+ /**
* Read opaque segment of data as a blob.
* @return blob of size expectedSize
* @throws IllegalArgumentException if the parcel has no more data
diff --git a/core/java/android/os/Looper.java b/core/java/android/os/Looper.java
index 3222fc4..d468972 100644
--- a/core/java/android/os/Looper.java
+++ b/core/java/android/os/Looper.java
@@ -112,10 +112,12 @@
/**
* Initialize the current thread as a looper, marking it as an
- * application's main looper. The main looper for your application
- * is created by the Android environment, so you should never need
- * to call this function yourself. See also: {@link #prepare()}
+ * application's main looper. See also: {@link #prepare()}
+ *
+ * @deprecated The main looper for your application is created by the Android environment,
+ * so you should never need to call this function yourself.
*/
+ @Deprecated
public static void prepareMainLooper() {
prepare(false);
synchronized (Looper.class) {
diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java
index deeeddc..2d70986d 100644
--- a/core/java/android/os/storage/StorageManager.java
+++ b/core/java/android/os/storage/StorageManager.java
@@ -2362,6 +2362,19 @@
}
}
+ /**
+ * Check whether the device supports filesystem checkpoint.
+ *
+ * @return true if the device supports filesystem checkpoint, false otherwise.
+ */
+ public boolean isCheckpointSupported() {
+ try {
+ return mStorageManager.supportsCheckpoint();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
private final Object mFuseAppLoopLock = new Object();
@GuardedBy("mFuseAppLoopLock")
diff --git a/core/java/android/provider/DeviceConfig.java b/core/java/android/provider/DeviceConfig.java
index 1d7e338..abf34ca 100644
--- a/core/java/android/provider/DeviceConfig.java
+++ b/core/java/android/provider/DeviceConfig.java
@@ -391,8 +391,9 @@
* Look up the values of multiple properties for a particular namespace. The lookup is atomic,
* such that the values of these properties cannot change between the time when the first is
* fetched and the time when the last is fetched.
- *
- * TODO: reference setProperties when it is added.
+ * <p>
+ * Each call to {@link #setProperties(Properties)} is also atomic and ensures that either none
+ * or all of the change is picked up here, but never only part of it.
*
* @param namespace The namespace containing the properties to look up.
* @param names The names of properties to look up, or empty to fetch all properties for the
@@ -560,6 +561,27 @@
}
/**
+ * Set all of the properties for a specific namespace. Pre-existing properties will be updated
+ * and new properties will be added if necessary. Any pre-existing properties for the specific
+ * namespace which are not part of the provided {@link Properties} object will be deleted from
+ * the namespace. These changes are all applied atomically, such that no calls to read or reset
+ * these properties can happen in the middle of this update.
+ * <p>
+ * Each call to {@link #getProperties(String, String...)} is also atomic and ensures that either
+ * none or all of this update is picked up, but never only part of it.
+ *
+ * @param properties the complete set of properties to set for a specific namespace.
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(WRITE_DEVICE_CONFIG)
+ public static boolean setProperties(@NonNull Properties properties) {
+ ContentResolver contentResolver = ActivityThread.currentApplication().getContentResolver();
+ return Settings.Config.setStrings(contentResolver, properties.getNamespace(),
+ properties.mMap);
+ }
+
+ /**
* Reset properties to their default values.
* <p>
* The method accepts an optional namespace parameter. If provided, only properties set within
@@ -703,23 +725,26 @@
List<String> pathSegments = uri.getPathSegments();
// pathSegments(0) is "config"
final String namespace = pathSegments.get(1);
- final String name = pathSegments.get(2);
- final String value;
+ Map<String, String> propertyMap = new ArrayMap<>();
try {
- value = getProperty(namespace, name);
+ Properties allProperties = getProperties(namespace);
+ for (int i = 2; i < pathSegments.size(); ++i) {
+ String key = pathSegments.get(i);
+ propertyMap.put(key, allProperties.getString(key, null));
+ }
} catch (SecurityException e) {
// Silently failing to not crash binder or listener threads.
Log.e(TAG, "OnPropertyChangedListener update failed: permission violation.");
return;
}
+ Properties properties = new Properties(namespace, propertyMap);
+
synchronized (sLock) {
for (int i = 0; i < sListeners.size(); i++) {
if (namespace.equals(sListeners.valueAt(i).first)) {
final OnPropertiesChangedListener listener = sListeners.keyAt(i);
sListeners.valueAt(i).second.execute(() -> {
- Map<String, String> propertyMap = new ArrayMap<>(1);
- propertyMap.put(name, value);
- listener.onPropertiesChanged(new Properties(namespace, propertyMap));
+ listener.onPropertiesChanged(properties);
});
}
}
@@ -741,7 +766,11 @@
}
/**
- * Interface for monitoring changes to properties.
+ * Interface for monitoring changes to properties. Implementations will receive callbacks when
+ * properties change, including a {@link Properties} object which contains a single namespace
+ * and all of the properties which changed for that namespace. This includes properties which
+ * were added, updated, or deleted. This is not necessarily a complete list of all properties
+ * belonging to the namespace, as properties which don't change are omitted.
* <p>
* Override {@link #onPropertiesChanged(Properties)} to handle callbacks for changes.
*
@@ -751,10 +780,13 @@
@TestApi
public interface OnPropertiesChangedListener {
/**
- * Called when one or more properties have changed.
+ * Called when one or more properties have changed, providing a Properties object with all
+ * of the changed properties. This object will contain only properties which have changed,
+ * not the complete set of all properties belonging to the namespace.
*
* @param properties Contains the complete collection of properties which have changed for a
- * single namespace.
+ * single namespace. This includes only those which were added, updated,
+ * or deleted.
*/
void onPropertiesChanged(@NonNull Properties properties);
}
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 3ac7deb..0af2c36 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -1960,6 +1960,11 @@
*/
public static final String CALL_METHOD_PREFIX_KEY = "_prefix";
+ /**
+ * @hide - String argument extra to the fast-path call()-based requests
+ */
+ public static final String CALL_METHOD_FLAGS_KEY = "_flags";
+
/** @hide - Private call() method to write to 'system' table */
public static final String CALL_METHOD_PUT_SYSTEM = "PUT_system";
@@ -1972,6 +1977,9 @@
/** @hide - Private call() method to write to 'configuration' table */
public static final String CALL_METHOD_PUT_CONFIG = "PUT_config";
+ /** @hide - Private call() method to write to and delete from the 'configuration' table */
+ public static final String CALL_METHOD_SET_ALL_CONFIG = "SET_ALL_config";
+
/** @hide - Private call() method to delete from the 'system' table */
public static final String CALL_METHOD_DELETE_SYSTEM = "DELETE_system";
@@ -2304,21 +2312,23 @@
private final String mCallGetCommand;
private final String mCallSetCommand;
private final String mCallListCommand;
+ private final String mCallSetAllCommand;
@GuardedBy("this")
private GenerationTracker mGenerationTracker;
public NameValueCache(Uri uri, String getCommand, String setCommand,
ContentProviderHolder providerHolder) {
- this(uri, getCommand, setCommand, null, providerHolder);
+ this(uri, getCommand, setCommand, null, null, providerHolder);
}
NameValueCache(Uri uri, String getCommand, String setCommand, String listCommand,
- ContentProviderHolder providerHolder) {
+ String setAllCommand, ContentProviderHolder providerHolder) {
mUri = uri;
mCallGetCommand = getCommand;
mCallSetCommand = setCommand;
mCallListCommand = listCommand;
+ mCallSetAllCommand = setAllCommand;
mProviderHolder = providerHolder;
}
@@ -2344,6 +2354,26 @@
return true;
}
+ public boolean setStringsForPrefix(ContentResolver cr, String prefix,
+ HashMap<String, String> keyValues) {
+ if (mCallSetAllCommand == null) {
+ // This NameValueCache does not support atomically setting multiple flags
+ return false;
+ }
+ try {
+ Bundle args = new Bundle();
+ args.putString(CALL_METHOD_PREFIX_KEY, prefix);
+ args.putSerializable(CALL_METHOD_FLAGS_KEY, keyValues);
+ IContentProvider cp = mProviderHolder.getProvider(cr);
+ cp.call(cr.getPackageName(), cr.getFeatureId(), mProviderHolder.mUri.getAuthority(),
+ mCallSetAllCommand, null, args);
+ } catch (RemoteException e) {
+ // Not supported by the remote side
+ return false;
+ }
+ return true;
+ }
+
@UnsupportedAppUsage
public String getStringForUser(ContentResolver cr, String name, final int userHandle) {
final boolean isSelf = (userHandle == UserHandle.myUserId());
@@ -6161,8 +6191,12 @@
"accessibility_shortcut_dialog_shown";
/**
- * Setting specifying the accessibility service to be toggled via the accessibility
- * shortcut. Must be its flattened {@link ComponentName}.
+ * Setting specifying the accessibility services, accessibility shortcut targets,
+ * or features to be toggled via the accessibility shortcut.
+ *
+ * <p> This is a colon-separated string list which contains the flattened
+ * {@link ComponentName} and the class name of a system class implementing a supported
+ * accessibility feature.
* @hide
*/
@UnsupportedAppUsage
@@ -6171,9 +6205,11 @@
"accessibility_shortcut_target_service";
/**
- * Setting specifying the accessibility service or feature to be toggled via the
- * accessibility button in the navigation bar. This is either a flattened
- * {@link ComponentName} or the class name of a system class implementing a supported
+ * Setting specifying the accessibility services, accessibility shortcut targets,
+ * or features to be toggled via the accessibility button in the navigation bar.
+ *
+ * <p> This is a colon-separated string list which contains the flattened
+ * {@link ComponentName} and the class name of a system class implementing a supported
* accessibility feature.
* @hide
*/
@@ -6334,6 +6370,9 @@
* zoom in the display content and is targeted to low vision users. The current
* magnification scale is controlled by {@link #ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE}.
*
+ * @deprecated Use {@link #ACCESSIBILITY_BUTTON_TARGET_COMPONENT} instead.
+ * {@link #ACCESSIBILITY_BUTTON_TARGET_COMPONENT} holds the magnification system class name
+ * when navigation bar magnification is enabled.
* @hide
*/
@SystemApi
@@ -7140,16 +7179,6 @@
public static final String VOICE_RECOGNITION_SERVICE = "voice_recognition_service";
/**
- * Stores whether an user has consented to have apps verified through PAM.
- * The value is boolean (1 or 0).
- *
- * @hide
- */
- @UnsupportedAppUsage
- public static final String PACKAGE_VERIFIER_USER_CONSENT =
- "package_verifier_user_consent";
-
- /**
* The {@link ComponentName} string of the selected spell checker service which is
* one of the services managed by the text service manager.
*
@@ -11889,6 +11918,7 @@
* as if they had been accepted by the user.
* @hide
*/
+ @TestApi
public static final String HIDE_ERROR_DIALOGS = "hide_error_dialogs";
/**
@@ -13718,6 +13748,7 @@
CALL_METHOD_GET_CONFIG,
CALL_METHOD_PUT_CONFIG,
CALL_METHOD_LIST_CONFIG,
+ CALL_METHOD_SET_ALL_CONFIG,
sProviderHolder);
/**
@@ -13792,6 +13823,29 @@
}
/**
+ * Clear all name/value pairs for the provided namespace and save new name/value pairs in
+ * their place.
+ *
+ * @param resolver to access the database with.
+ * @param namespace to which the names should be set.
+ * @param keyValues map of key names (without the prefix) to values.
+ * @return
+ *
+ * @hide
+ */
+ @RequiresPermission(Manifest.permission.WRITE_DEVICE_CONFIG)
+ static boolean setStrings(@NonNull ContentResolver resolver, @NonNull String namespace,
+ @NonNull Map<String, String> keyValues) {
+ HashMap<String, String> compositeKeyValueMap = new HashMap<>(keyValues.keySet().size());
+ for (Map.Entry<String, String> entry : keyValues.entrySet()) {
+ compositeKeyValueMap.put(
+ createCompositeName(namespace, entry.getKey()), entry.getValue());
+ }
+ return sNameValueCache.setStringsForPrefix(resolver, createPrefix(namespace),
+ compositeKeyValueMap);
+ }
+
+ /**
* Reset the values to their defaults.
* <p>
* The method accepts an optional prefix parameter. If provided, only pairs with a name that
diff --git a/core/java/android/util/StatsEvent.java b/core/java/android/util/StatsEvent.java
index 10c9d87..d7ec30c 100644
--- a/core/java/android/util/StatsEvent.java
+++ b/core/java/android/util/StatsEvent.java
@@ -45,6 +45,166 @@
* @hide
**/
public final class StatsEvent implements Parcelable {
+ // Type Ids.
+ /**
+ * @hide
+ **/
+ @VisibleForTesting
+ public static final byte TYPE_INT = 0x00;
+
+ /**
+ * @hide
+ **/
+ @VisibleForTesting
+ public static final byte TYPE_LONG = 0x01;
+
+ /**
+ * @hide
+ **/
+ @VisibleForTesting
+ public static final byte TYPE_STRING = 0x02;
+
+ /**
+ * @hide
+ **/
+ @VisibleForTesting
+ public static final byte TYPE_LIST = 0x03;
+
+ /**
+ * @hide
+ **/
+ @VisibleForTesting
+ public static final byte TYPE_FLOAT = 0x04;
+
+ /**
+ * @hide
+ **/
+ @VisibleForTesting
+ public static final byte TYPE_BOOLEAN = 0x05;
+
+ /**
+ * @hide
+ **/
+ @VisibleForTesting
+ public static final byte TYPE_BYTE_ARRAY = 0x06;
+
+ /**
+ * @hide
+ **/
+ @VisibleForTesting
+ public static final byte TYPE_OBJECT = 0x07;
+
+ /**
+ * @hide
+ **/
+ @VisibleForTesting
+ public static final byte TYPE_KEY_VALUE_PAIRS = 0x08;
+
+ /**
+ * @hide
+ **/
+ @VisibleForTesting
+ public static final byte TYPE_ATTRIBUTION_CHAIN = 0x09;
+
+ /**
+ * @hide
+ **/
+ @VisibleForTesting
+ public static final byte TYPE_ERRORS = 0x0F;
+
+ // Error flags.
+ /**
+ * @hide
+ **/
+ @VisibleForTesting
+ public static final int ERROR_NO_TIMESTAMP = 0x1;
+
+ /**
+ * @hide
+ **/
+ @VisibleForTesting
+ public static final int ERROR_NO_ATOM_ID = 0x2;
+
+ /**
+ * @hide
+ **/
+ @VisibleForTesting
+ public static final int ERROR_OVERFLOW = 0x4;
+
+ /**
+ * @hide
+ **/
+ @VisibleForTesting
+ public static final int ERROR_ATTRIBUTION_CHAIN_TOO_LONG = 0x8;
+
+ /**
+ * @hide
+ **/
+ @VisibleForTesting
+ public static final int ERROR_TOO_MANY_KEY_VALUE_PAIRS = 0x10;
+
+ /**
+ * @hide
+ **/
+ @VisibleForTesting
+ public static final int ERROR_ANNOTATION_DOES_NOT_FOLLOW_FIELD = 0x20;
+
+ /**
+ * @hide
+ **/
+ @VisibleForTesting
+ public static final int ERROR_INVALID_ANNOTATION_ID = 0x40;
+
+ /**
+ * @hide
+ **/
+ @VisibleForTesting
+ public static final int ERROR_ANNOTATION_ID_TOO_LARGE = 0x80;
+
+ /**
+ * @hide
+ **/
+ @VisibleForTesting
+ public static final int ERROR_TOO_MANY_ANNOTATIONS = 0x100;
+
+ /**
+ * @hide
+ **/
+ @VisibleForTesting
+ public static final int ERROR_TOO_MANY_FIELDS = 0x200;
+
+ /**
+ * @hide
+ **/
+ @VisibleForTesting
+ public static final int ERROR_ATTRIBUTION_UIDS_TAGS_SIZES_NOT_EQUAL = 0x400;
+
+ // Size limits.
+
+ /**
+ * @hide
+ **/
+ @VisibleForTesting
+ public static final int MAX_ANNOTATION_COUNT = 15;
+
+ /**
+ * @hide
+ **/
+ @VisibleForTesting
+ public static final int MAX_ATTRIBUTION_NODES = 127;
+
+ /**
+ * @hide
+ **/
+ @VisibleForTesting
+ public static final int MAX_NUM_ELEMENTS = 127;
+
+ /**
+ * @hide
+ **/
+ @VisibleForTesting
+ public static final int MAX_KEY_VALUE_PAIRS = 127;
+
private static final int LOGGER_ENTRY_MAX_PAYLOAD = 4068;
// Max payload size is 4 bytes less as 4 bytes are reserved for statsEventTag.
@@ -69,24 +229,75 @@
return new StatsEvent.Builder(Buffer.obtain());
}
- int getAtomId() {
+ /**
+ * Get the atom Id of the atom encoded in this StatsEvent object.
+ *
+ * @hide
+ **/
+ public int getAtomId() {
return mAtomId;
}
+ /**
+ * Get the byte array that contains the encoded payload that can be sent to statsd.
+ *
+ * @hide
+ **/
@NonNull
- byte[] getBytes() {
+ public byte[] getBytes() {
return mBuffer.getBytes();
}
- int getNumBytes() {
+ /**
+ * Get the number of bytes used to encode the StatsEvent payload.
+ *
+ * @hide
+ **/
+ public int getNumBytes() {
return mNumBytes;
}
- void release() {
+ /**
+ * Recycle this StatsEvent object.
+ **/
+ public void release() {
mBuffer.release();
}
/**
+ * Boilerplate for Parcel.
+ */
+ public static final @NonNull Parcelable.Creator<StatsEvent> CREATOR =
+ new Parcelable.Creator<StatsEvent>() {
+ public StatsEvent createFromParcel(Parcel in) {
+ // Purposefully leaving this method not implemented.
+ throw new RuntimeException("Not implemented");
+ }
+
+ public StatsEvent[] newArray(int size) {
+ // Purposefully leaving this method not implemented.
+ throw new RuntimeException("Not implemented");
+ }
+ };
+
+ /**
+ * Boilerplate for Parcel.
+ */
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeInt(mAtomId);
+ out.writeInt(getNumBytes());
+ out.writeByteArray(getBytes());
+ }
+
+ /**
+ * Boilerplate for Parcel.
+ */
+ public int describeContents() {
+ return 0;
+ }
+
+
+ /**
* Builder for constructing a StatsEvent object.
*
* <p>This class defines and encapsulates the socket encoding for the buffer.
@@ -114,41 +325,8 @@
* .addBooleanAnnotation(annotation1Id, true)
* .build();
* </pre>
- * @hide
**/
public static final class Builder {
- // Type Ids.
- private static final byte TYPE_INT = 0x00;
- private static final byte TYPE_LONG = 0x01;
- private static final byte TYPE_STRING = 0x02;
- private static final byte TYPE_LIST = 0x03;
- private static final byte TYPE_FLOAT = 0x04;
- private static final byte TYPE_BOOLEAN = 0x05;
- private static final byte TYPE_BYTE_ARRAY = 0x06;
- private static final byte TYPE_OBJECT = 0x07;
- private static final byte TYPE_KEY_VALUE_PAIRS = 0x08;
- private static final byte TYPE_ATTRIBUTION_CHAIN = 0x09;
- private static final byte TYPE_ERRORS = 0x0F;
-
- // Error flags.
- private static final int ERROR_NO_TIMESTAMP = 0x1;
- private static final int ERROR_NO_ATOM_ID = 0x2;
- private static final int ERROR_OVERFLOW = 0x4;
- private static final int ERROR_ATTRIBUTION_CHAIN_TOO_LONG = 0x8;
- private static final int ERROR_TOO_MANY_KEY_VALUE_PAIRS = 0x10;
- private static final int ERROR_ANNOTATION_DOES_NOT_FOLLOW_FIELD = 0x20;
- private static final int ERROR_INVALID_ANNOTATION_ID = 0x40;
- private static final int ERROR_ANNOTATION_ID_TOO_LARGE = 0x80;
- private static final int ERROR_TOO_MANY_ANNOTATIONS = 0x100;
- private static final int ERROR_TOO_MANY_FIELDS = 0x200;
- private static final int ERROR_ATTRIBUTION_UIDS_TAGS_SIZES_NOT_EQUAL = 0x400;
-
- // Size limits.
- private static final int MAX_ANNOTATION_COUNT = 15;
- private static final int MAX_ATTRIBUTION_NODES = 127;
- private static final int MAX_NUM_ELEMENTS = 127;
- private static final int MAX_KEY_VALUE_PAIRS = 127;
-
// Fixed positions.
private static final int POS_NUM_ELEMENTS = 1;
private static final int POS_TIMESTAMP_NS = POS_NUM_ELEMENTS + Byte.BYTES;
@@ -290,7 +468,7 @@
* @param tags array of tags in the attribution nodes.
**/
@NonNull
- public Builder writeAttributionNode(
+ public Builder writeAttributionChain(
@NonNull final int[] uids, @NonNull final String[] tags) {
final byte numUids = (byte) uids.length;
final byte numTags = (byte) tags.length;
@@ -633,39 +811,4 @@
return 0;
}
}
-
- /**
- * Boilerplate for Parcel.
- *
- * @hide
- */
- public static final @NonNull Parcelable.Creator<StatsEvent> CREATOR =
- new Parcelable.Creator<StatsEvent>() {
- public StatsEvent createFromParcel(Parcel in) {
- // Purposefully leaving this method not implemented.
- throw new RuntimeException("Not implemented");
- }
-
- public StatsEvent[] newArray(int size) {
- // Purposefully leaving this method not implemented.
- throw new RuntimeException("Not implemented");
- }
- };
-
- /**
- * @hide
- */
- public void writeToParcel(Parcel out, int flags) {
- out.writeInt(mAtomId);
- out.writeInt(getNumBytes());
- out.writeByteArray(getBytes());
- }
-
- /**
- * Boilerplate for Parcel.
- */
- public int describeContents() {
- return 0;
- }
-
}
diff --git a/core/java/android/util/TimingLogger.java b/core/java/android/util/TimingLogger.java
index be442da..5a4a512 100644
--- a/core/java/android/util/TimingLogger.java
+++ b/core/java/android/util/TimingLogger.java
@@ -44,7 +44,14 @@
* D/TAG ( 3459): methodA: 6 ms, work C
* D/TAG ( 3459): methodA: end, 16 ms
* </pre>
+ *
+ * @deprecated Use {@link android.os.Trace}, or
+ * <a href="https://developer.android.com/studio/profile/benchmark">Android Studio</a>. In
+ * general, milliseconds is the wrong granularity for method-level tracing. Rounding errors
+ * can overemphasize cheap operations, or underemphasize repeated operations. This timing
+ * system also does not take CPU scheduling or frequency into account.
*/
+@Deprecated
public class TimingLogger {
/**
diff --git a/core/java/android/view/IDisplayWindowListener.aidl b/core/java/android/view/IDisplayWindowListener.aidl
index 725cd6f..973a208 100644
--- a/core/java/android/view/IDisplayWindowListener.aidl
+++ b/core/java/android/view/IDisplayWindowListener.aidl
@@ -16,12 +16,16 @@
package android.view;
+import android.content.res.Configuration;
+
/**
* Interface to listen for changes to display window-containers.
*
- * This differs from DisplayManager's DisplayListener:
+ * This differs from DisplayManager's DisplayListener in a couple ways:
* - onDisplayAdded is always called after the display is actually added to the WM hierarchy.
* This corresponds to the DisplayContent and not the raw Dislay from DisplayManager.
+ * - onDisplayConfigurationChanged is called for all configuration changes, not just changes
+ * to displayinfo (eg. windowing-mode).
*
* @hide
*/
@@ -33,6 +37,11 @@
void onDisplayAdded(int displayId);
/**
+ * Called when a display's window-container configuration has changed.
+ */
+ void onDisplayConfigurationChanged(int displayId, in Configuration newConfig);
+
+ /**
* Called when a display is removed from the hierarchy.
*/
void onDisplayRemoved(int displayId);
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index db76b71..9d4f3878 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -8732,7 +8732,7 @@
structure.setContextClickable(true);
}
structure.setClassName(getAccessibilityClassName().toString());
- structure.setContentDescription(mContentDescription);
+ structure.setContentDescription(getContentDescription());
}
/**
@@ -9939,8 +9939,8 @@
info.setImportantForAccessibility(isImportantForAccessibility());
info.setPackageName(mContext.getPackageName());
info.setClassName(getAccessibilityClassName());
- info.setStateDescription(mStateDescription);
- info.setContentDescription(mContentDescription);
+ info.setStateDescription(getStateDescription());
+ info.setContentDescription(getContentDescription());
info.setEnabled(isEnabled());
info.setClickable(isClickable());
@@ -10323,7 +10323,7 @@
* @see #setStateDescription(CharSequence)
*/
@ViewDebug.ExportedProperty(category = "accessibility")
- public @Nullable CharSequence getStateDescription() {
+ public final @Nullable CharSequence getStateDescription() {
return mStateDescription;
}
@@ -13717,7 +13717,7 @@
*/
@UnsupportedAppUsage
public CharSequence getIterableTextForAccessibility() {
- return mContentDescription;
+ return getContentDescription();
}
/**
@@ -29498,10 +29498,9 @@
stream.addProperty("text:textAlignment", getTextAlignment());
// accessibility
+ CharSequence contentDescription = getContentDescription();
stream.addProperty("accessibility:contentDescription",
- mContentDescription == null ? "" : mContentDescription.toString());
- stream.addProperty("accessibility:stateDescription",
- mStateDescription == null ? "" : mStateDescription.toString());
+ contentDescription == null ? "" : contentDescription.toString());
stream.addProperty("accessibility:labelFor", getLabelFor());
stream.addProperty("accessibility:importantForAccessibility", getImportantForAccessibility());
}
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 89b111d..afa661e 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -4966,6 +4966,8 @@
protected static final int FINISH_HANDLED = 1;
protected static final int FINISH_NOT_HANDLED = 2;
+ private String mTracePrefix;
+
/**
* Creates an input stage.
* @param next The next stage to which events should be forwarded.
@@ -4983,7 +4985,14 @@
} else if (shouldDropInputEvent(q)) {
finish(q, false);
} else {
- apply(q, onProcess(q));
+ traceEvent(q, Trace.TRACE_TAG_VIEW);
+ final int result;
+ try {
+ result = onProcess(q);
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_VIEW);
+ }
+ apply(q, result);
}
}
@@ -5093,6 +5102,17 @@
return false;
}
}
+
+ private void traceEvent(QueuedInputEvent q, long traceTag) {
+ if (!Trace.isTagEnabled(traceTag)) {
+ return;
+ }
+
+ if (mTracePrefix == null) {
+ mTracePrefix = getClass().getSimpleName();
+ }
+ Trace.traceBegin(traceTag, mTracePrefix + " seq#=" + q.mEvent.getSequenceNumber());
+ }
}
/**
@@ -7709,26 +7729,46 @@
private void deliverInputEvent(QueuedInputEvent q) {
Trace.asyncTraceBegin(Trace.TRACE_TAG_VIEW, "deliverInputEvent",
q.mEvent.getSequenceNumber());
- if (mInputEventConsistencyVerifier != null) {
- mInputEventConsistencyVerifier.onInputEvent(q.mEvent, 0);
- }
- InputStage stage;
- if (q.shouldSendToSynthesizer()) {
- stage = mSyntheticInputStage;
- } else {
- stage = q.shouldSkipIme() ? mFirstPostImeInputStage : mFirstInputStage;
+ if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
+ Trace.traceBegin(Trace.TRACE_TAG_VIEW, "deliverInputEvent src=0x"
+ + Integer.toHexString(q.mEvent.getSource()) + " eventTimeNano="
+ + q.mEvent.getEventTimeNano() + " seq#=" + q.mEvent.getSequenceNumber());
}
+ try {
+ if (mInputEventConsistencyVerifier != null) {
+ Trace.traceBegin(Trace.TRACE_TAG_VIEW, "verifyEventConsistency");
+ try {
+ mInputEventConsistencyVerifier.onInputEvent(q.mEvent, 0);
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_VIEW);
+ }
+ }
- if (q.mEvent instanceof KeyEvent) {
- mUnhandledKeyManager.preDispatch((KeyEvent) q.mEvent);
- }
+ InputStage stage;
+ if (q.shouldSendToSynthesizer()) {
+ stage = mSyntheticInputStage;
+ } else {
+ stage = q.shouldSkipIme() ? mFirstPostImeInputStage : mFirstInputStage;
+ }
- if (stage != null) {
- handleWindowFocusChanged();
- stage.deliver(q);
- } else {
- finishInputEvent(q);
+ if (q.mEvent instanceof KeyEvent) {
+ Trace.traceBegin(Trace.TRACE_TAG_VIEW, "preDispatchToUnhandledKeyManager");
+ try {
+ mUnhandledKeyManager.preDispatch((KeyEvent) q.mEvent);
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_VIEW);
+ }
+ }
+
+ if (stage != null) {
+ handleWindowFocusChanged();
+ stage.deliver(q);
+ } else {
+ finishInputEvent(q);
+ }
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_VIEW);
}
}
diff --git a/core/java/android/view/inline/InlineContentView.java b/core/java/android/view/inline/InlineContentView.java
new file mode 100644
index 0000000..4bc2176
--- /dev/null
+++ b/core/java/android/view/inline/InlineContentView.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view.inline;
+
+import android.annotation.NonNull;
+import android.content.Context;
+import android.graphics.PixelFormat;
+import android.view.SurfaceControl;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
+
+/**
+ * This class represents a view that can hold an opaque content that may be from a different source.
+ *
+ * @hide
+ */
+public class InlineContentView extends SurfaceView {
+ public InlineContentView(@NonNull Context context,
+ @NonNull SurfaceControl surfaceControl) {
+ super(context);
+ setZOrderOnTop(true);
+ getHolder().addCallback(new SurfaceHolder.Callback() {
+ @Override
+ public void surfaceCreated(SurfaceHolder holder) {
+ holder.setFormat(PixelFormat.TRANSPARENT);
+ new SurfaceControl.Transaction()
+ .reparent(surfaceControl, getSurfaceControl())
+ .setVisibility(surfaceControl, /* visible */ true)
+ .apply();
+ }
+
+ @Override
+ public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
+ // TODO(b/137800469): implement this.
+ }
+
+ @Override
+ public void surfaceDestroyed(SurfaceHolder holder) {
+ // TODO(b/137800469): implement this.
+ }
+ });
+ }
+}
diff --git a/core/java/android/view/inline/InlinePresentationSpec.aidl b/core/java/android/view/inline/InlinePresentationSpec.aidl
new file mode 100644
index 0000000..efa46c8
--- /dev/null
+++ b/core/java/android/view/inline/InlinePresentationSpec.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view.inline;
+
+parcelable InlinePresentationSpec;
diff --git a/core/java/android/view/inline/InlinePresentationSpec.java b/core/java/android/view/inline/InlinePresentationSpec.java
new file mode 100644
index 0000000..1eddef5
--- /dev/null
+++ b/core/java/android/view/inline/InlinePresentationSpec.java
@@ -0,0 +1,244 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view.inline;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.Parcelable;
+import android.util.Size;
+
+import com.android.internal.util.DataClass;
+
+/**
+ * This class represents the presentation specification by which an inline suggestion
+ * should abide when constructing its UI. Since suggestions are inlined in a
+ * host application while provided by another source, they need to be consistent
+ * with the host's look at feel to allow building smooth and integrated UIs.
+ */
+@DataClass(genEqualsHashCode = true, genToString = true, genBuilder = true)
+public final class InlinePresentationSpec implements Parcelable {
+ /** The minimal size of the suggestion. */
+ @NonNull
+ private final Size mMinSize;
+ /** The maximal size of the suggestion. */
+ @NonNull
+ private final Size mMaxSize;
+
+ // TODO(b/137800469): add more attributes, such as text appearance info.
+
+ /** @hide */
+ @DataClass.Suppress({"setMaxSize", "setMinSize"})
+ abstract static class BaseBuilder {
+ }
+
+
+
+ // Code below generated by codegen v1.0.14.
+ //
+ // DO NOT MODIFY!
+ // CHECKSTYLE:OFF Generated code
+ //
+ // To regenerate run:
+ // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/view/inline/InlinePresentationSpec.java
+ //
+ // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
+ // Settings > Editor > Code Style > Formatter Control
+ //@formatter:off
+
+
+ @DataClass.Generated.Member
+ /* package-private */ InlinePresentationSpec(
+ @NonNull Size minSize,
+ @NonNull Size maxSize) {
+ this.mMinSize = minSize;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mMinSize);
+ this.mMaxSize = maxSize;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mMaxSize);
+
+ // onConstructed(); // You can define this method to get a callback
+ }
+
+ /**
+ * The minimal size of the suggestion.
+ */
+ @DataClass.Generated.Member
+ public @NonNull Size getMinSize() {
+ return mMinSize;
+ }
+
+ /**
+ * The maximal size of the suggestion.
+ */
+ @DataClass.Generated.Member
+ public @NonNull Size getMaxSize() {
+ return mMaxSize;
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public String toString() {
+ // You can override field toString logic by defining methods like:
+ // String fieldNameToString() { ... }
+
+ return "InlinePresentationSpec { " +
+ "minSize = " + mMinSize + ", " +
+ "maxSize = " + mMaxSize +
+ " }";
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public boolean equals(@Nullable Object o) {
+ // You can override field equality logic by defining either of the methods like:
+ // boolean fieldNameEquals(InlinePresentationSpec other) { ... }
+ // boolean fieldNameEquals(FieldType otherValue) { ... }
+
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ @SuppressWarnings("unchecked")
+ InlinePresentationSpec that = (InlinePresentationSpec) o;
+ //noinspection PointlessBooleanExpression
+ return true
+ && java.util.Objects.equals(mMinSize, that.mMinSize)
+ && java.util.Objects.equals(mMaxSize, that.mMaxSize);
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public int hashCode() {
+ // You can override field hashCode logic by defining methods like:
+ // int fieldNameHashCode() { ... }
+
+ int _hash = 1;
+ _hash = 31 * _hash + java.util.Objects.hashCode(mMinSize);
+ _hash = 31 * _hash + java.util.Objects.hashCode(mMaxSize);
+ return _hash;
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public void writeToParcel(@NonNull android.os.Parcel dest, int flags) {
+ // You can override field parcelling by defining methods like:
+ // void parcelFieldName(Parcel dest, int flags) { ... }
+
+ dest.writeSize(mMinSize);
+ dest.writeSize(mMaxSize);
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public int describeContents() { return 0; }
+
+ /** @hide */
+ @SuppressWarnings({"unchecked", "RedundantCast"})
+ @DataClass.Generated.Member
+ /* package-private */ InlinePresentationSpec(@NonNull android.os.Parcel in) {
+ // You can override field unparcelling by defining methods like:
+ // static FieldType unparcelFieldName(Parcel in) { ... }
+
+ Size minSize = (Size) in.readSize();
+ Size maxSize = (Size) in.readSize();
+
+ this.mMinSize = minSize;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mMinSize);
+ this.mMaxSize = maxSize;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mMaxSize);
+
+ // onConstructed(); // You can define this method to get a callback
+ }
+
+ @DataClass.Generated.Member
+ public static final @NonNull Parcelable.Creator<InlinePresentationSpec> CREATOR
+ = new Parcelable.Creator<InlinePresentationSpec>() {
+ @Override
+ public InlinePresentationSpec[] newArray(int size) {
+ return new InlinePresentationSpec[size];
+ }
+
+ @Override
+ public InlinePresentationSpec createFromParcel(@NonNull android.os.Parcel in) {
+ return new InlinePresentationSpec(in);
+ }
+ };
+
+ /**
+ * A builder for {@link InlinePresentationSpec}
+ */
+ @SuppressWarnings("WeakerAccess")
+ @DataClass.Generated.Member
+ public static final class Builder extends BaseBuilder {
+
+ private @NonNull Size mMinSize;
+ private @NonNull Size mMaxSize;
+
+ private long mBuilderFieldsSet = 0L;
+
+ /**
+ * Creates a new Builder.
+ *
+ * @param minSize
+ * The minimal size of the suggestion.
+ * @param maxSize
+ * The maximal size of the suggestion.
+ */
+ public Builder(
+ @NonNull Size minSize,
+ @NonNull Size maxSize) {
+ mMinSize = minSize;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mMinSize);
+ mMaxSize = maxSize;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mMaxSize);
+ }
+
+ /** Builds the instance. This builder should not be touched after calling this! */
+ public @NonNull InlinePresentationSpec build() {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x4; // Mark builder used
+
+ InlinePresentationSpec o = new InlinePresentationSpec(
+ mMinSize,
+ mMaxSize);
+ return o;
+ }
+
+ private void checkNotUsed() {
+ if ((mBuilderFieldsSet & 0x4) != 0) {
+ throw new IllegalStateException(
+ "This Builder should not be reused. Use a new Builder instance instead");
+ }
+ }
+ }
+
+ @DataClass.Generated(
+ time = 1574406062532L,
+ codegenVersion = "1.0.14",
+ sourceFile = "frameworks/base/core/java/android/view/inline/InlinePresentationSpec.java",
+ inputSignatures = "private final @android.annotation.NonNull android.util.Size mMinSize\nprivate final @android.annotation.NonNull android.util.Size mMaxSize\nclass InlinePresentationSpec extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genToString=true, genBuilder=true)\nclass BaseBuilder extends java.lang.Object implements []")
+ @Deprecated
+ private void __metadata() {}
+
+
+ //@formatter:on
+ // End of generated code
+
+}
diff --git a/core/java/android/view/inputmethod/InlineSuggestion.aidl b/core/java/android/view/inputmethod/InlineSuggestion.aidl
new file mode 100644
index 0000000..208d964
--- /dev/null
+++ b/core/java/android/view/inputmethod/InlineSuggestion.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view.inputmethod;
+
+parcelable InlineSuggestion;
diff --git a/core/java/android/view/inputmethod/InlineSuggestion.java b/core/java/android/view/inputmethod/InlineSuggestion.java
new file mode 100644
index 0000000..25e34d3
--- /dev/null
+++ b/core/java/android/view/inputmethod/InlineSuggestion.java
@@ -0,0 +1,285 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view.inputmethod;
+
+import android.annotation.CallbackExecutor;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.Context;
+import android.os.AsyncTask;
+import android.os.Parcelable;
+import android.os.RemoteException;
+import android.util.Size;
+import android.util.Slog;
+import android.view.SurfaceControl;
+import android.view.View;
+import android.view.inline.InlineContentView;
+import android.view.inline.InlinePresentationSpec;
+
+import com.android.internal.util.DataClass;
+import com.android.internal.view.inline.IInlineContentCallback;
+import com.android.internal.view.inline.IInlineContentProvider;
+
+import java.lang.ref.WeakReference;
+import java.util.concurrent.Executor;
+import java.util.function.Consumer;
+
+/**
+ * This class represents an inline suggestion which is made by one app
+ * and can be embedded into the UI of another. Suggestions may contain
+ * sensitive information not known to the host app which needs to be
+ * protected from spoofing. To address that the suggestion view inflated
+ * on demand for embedding is created in such a way that the hosting app
+ * cannot introspect its content and cannot interact with it.
+ */
+@DataClass(
+ genEqualsHashCode = true,
+ genToString = true,
+ genHiddenConstDefs = true,
+ genHiddenConstructor = true)
+@DataClass.Suppress({"getContentProvider"})
+public final class InlineSuggestion implements Parcelable {
+
+ private static final String TAG = "InlineSuggestion";
+
+ private final @NonNull InlineSuggestionInfo mInfo;
+
+ private final @Nullable IInlineContentProvider mContentProvider;
+
+ /**
+ * Inflates a view with the content of this suggestion at a specific size.
+ * The size must be between the {@link InlinePresentationSpec#getMinSize() min size}
+ * and the {@link InlinePresentationSpec#getMaxSize() max size} of the presentation
+ * spec returned by {@link InlineSuggestionInfo#getPresentationSpec()}. If an invalid
+ * argument is passed an exception is thrown.
+ *
+ * @param context Context in which to inflate the view.
+ * @param size The size at which to inflate the suggestion.
+ * @param callback Callback for receiving the inflated view.
+ */
+ public void inflate(@NonNull Context context, @NonNull Size size,
+ @NonNull @CallbackExecutor Executor callbackExecutor,
+ @NonNull Consumer<View> callback) {
+ final Size minSize = mInfo.getPresentationSpec().getMinSize();
+ final Size maxSize = mInfo.getPresentationSpec().getMaxSize();
+ if (size.getHeight() < minSize.getHeight() || size.getHeight() > maxSize.getHeight()
+ || size.getWidth() < minSize.getWidth() || size.getWidth() > maxSize.getWidth()) {
+ throw new IllegalArgumentException("size not between min:"
+ + minSize + " and max:" + maxSize);
+ }
+ AsyncTask.THREAD_POOL_EXECUTOR.execute(() -> {
+ if (mContentProvider == null) {
+ callback.accept(/* view */ null);
+ return;
+ }
+ // TODO(b/137800469): keep a strong reference to the contentCallback so it doesn't
+ // get GC'd. Also add a isInflated() method and make sure the view can only be
+ // inflated once.
+ try {
+ InlineContentCallbackImpl contentCallback = new InlineContentCallbackImpl(context,
+ callbackExecutor, callback);
+ mContentProvider.provideContent(size.getWidth(), size.getHeight(),
+ new InlineContentCallbackWrapper(contentCallback));
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Error creating suggestion content surface: " + e);
+ callback.accept(/* view */ null);
+ }
+ });
+ }
+
+ private static final class InlineContentCallbackWrapper extends IInlineContentCallback.Stub {
+
+ private final WeakReference<InlineContentCallbackImpl> mCallbackImpl;
+
+ InlineContentCallbackWrapper(InlineContentCallbackImpl callbackImpl) {
+ mCallbackImpl = new WeakReference<>(callbackImpl);
+ }
+
+ @Override
+ public void onContent(SurfaceControl content) {
+ final InlineContentCallbackImpl callbackImpl = mCallbackImpl.get();
+ if (callbackImpl != null) {
+ callbackImpl.onContent(content);
+ }
+ }
+ }
+
+ private static final class InlineContentCallbackImpl {
+
+ private final @NonNull Context mContext;
+ private final @NonNull Executor mCallbackExecutor;
+ private final @NonNull Consumer<View> mCallback;
+
+ InlineContentCallbackImpl(@NonNull Context context,
+ @NonNull @CallbackExecutor Executor callbackExecutor,
+ @NonNull Consumer<View> callback) {
+ mContext = context;
+ mCallbackExecutor = callbackExecutor;
+ mCallback = callback;
+ }
+
+ public void onContent(SurfaceControl content) {
+ if (content == null) {
+ mCallbackExecutor.execute(() -> mCallback.accept(/* view */null));
+ } else {
+ mCallbackExecutor.execute(
+ () -> mCallback.accept(new InlineContentView(mContext, content)));
+ }
+ }
+ }
+
+
+
+ // Code below generated by codegen v1.0.14.
+ //
+ // DO NOT MODIFY!
+ // CHECKSTYLE:OFF Generated code
+ //
+ // To regenerate run:
+ // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/view/inputmethod/InlineSuggestion.java
+ //
+ // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
+ // Settings > Editor > Code Style > Formatter Control
+ //@formatter:off
+
+
+ /**
+ * Creates a new InlineSuggestion.
+ *
+ * @hide
+ */
+ @DataClass.Generated.Member
+ public InlineSuggestion(
+ @NonNull InlineSuggestionInfo info,
+ @Nullable IInlineContentProvider contentProvider) {
+ this.mInfo = info;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mInfo);
+ this.mContentProvider = contentProvider;
+
+ // onConstructed(); // You can define this method to get a callback
+ }
+
+ @DataClass.Generated.Member
+ public @NonNull InlineSuggestionInfo getInfo() {
+ return mInfo;
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public String toString() {
+ // You can override field toString logic by defining methods like:
+ // String fieldNameToString() { ... }
+
+ return "InlineSuggestion { " +
+ "info = " + mInfo + ", " +
+ "contentProvider = " + mContentProvider +
+ " }";
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public boolean equals(@Nullable Object o) {
+ // You can override field equality logic by defining either of the methods like:
+ // boolean fieldNameEquals(InlineSuggestion other) { ... }
+ // boolean fieldNameEquals(FieldType otherValue) { ... }
+
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ @SuppressWarnings("unchecked")
+ InlineSuggestion that = (InlineSuggestion) o;
+ //noinspection PointlessBooleanExpression
+ return true
+ && java.util.Objects.equals(mInfo, that.mInfo)
+ && java.util.Objects.equals(mContentProvider, that.mContentProvider);
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public int hashCode() {
+ // You can override field hashCode logic by defining methods like:
+ // int fieldNameHashCode() { ... }
+
+ int _hash = 1;
+ _hash = 31 * _hash + java.util.Objects.hashCode(mInfo);
+ _hash = 31 * _hash + java.util.Objects.hashCode(mContentProvider);
+ return _hash;
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public void writeToParcel(@NonNull android.os.Parcel dest, int flags) {
+ // You can override field parcelling by defining methods like:
+ // void parcelFieldName(Parcel dest, int flags) { ... }
+
+ byte flg = 0;
+ if (mContentProvider != null) flg |= 0x2;
+ dest.writeByte(flg);
+ dest.writeTypedObject(mInfo, flags);
+ if (mContentProvider != null) dest.writeStrongInterface(mContentProvider);
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public int describeContents() { return 0; }
+
+ /** @hide */
+ @SuppressWarnings({"unchecked", "RedundantCast"})
+ @DataClass.Generated.Member
+ /* package-private */ InlineSuggestion(@NonNull android.os.Parcel in) {
+ // You can override field unparcelling by defining methods like:
+ // static FieldType unparcelFieldName(Parcel in) { ... }
+
+ byte flg = in.readByte();
+ InlineSuggestionInfo info = (InlineSuggestionInfo) in.readTypedObject(InlineSuggestionInfo.CREATOR);
+ IInlineContentProvider contentProvider = (flg & 0x2) == 0 ? null : IInlineContentProvider.Stub.asInterface(in.readStrongBinder());
+
+ this.mInfo = info;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mInfo);
+ this.mContentProvider = contentProvider;
+
+ // onConstructed(); // You can define this method to get a callback
+ }
+
+ @DataClass.Generated.Member
+ public static final @NonNull Parcelable.Creator<InlineSuggestion> CREATOR
+ = new Parcelable.Creator<InlineSuggestion>() {
+ @Override
+ public InlineSuggestion[] newArray(int size) {
+ return new InlineSuggestion[size];
+ }
+
+ @Override
+ public InlineSuggestion createFromParcel(@NonNull android.os.Parcel in) {
+ return new InlineSuggestion(in);
+ }
+ };
+
+ @DataClass.Generated(
+ time = 1574446220398L,
+ codegenVersion = "1.0.14",
+ sourceFile = "frameworks/base/core/java/android/view/inputmethod/InlineSuggestion.java",
+ inputSignatures = "private static final java.lang.String TAG\nprivate final @android.annotation.NonNull android.view.inputmethod.InlineSuggestionInfo mInfo\nprivate final @android.annotation.Nullable com.android.internal.view.inline.IInlineContentProvider mContentProvider\npublic void inflate(android.content.Context,android.util.Size,java.util.concurrent.Executor,java.util.function.Consumer<android.view.View>)\nclass InlineSuggestion extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genToString=true, genHiddenConstDefs=true, genHiddenConstructor=true)")
+ @Deprecated
+ private void __metadata() {}
+
+
+ //@formatter:on
+ // End of generated code
+
+}
diff --git a/core/java/android/view/inputmethod/InlineSuggestionInfo.aidl b/core/java/android/view/inputmethod/InlineSuggestionInfo.aidl
new file mode 100644
index 0000000..168bd0b
--- /dev/null
+++ b/core/java/android/view/inputmethod/InlineSuggestionInfo.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view.inputmethod;
+
+parcelable InlineSuggestionInfo;
diff --git a/core/java/android/view/inputmethod/InlineSuggestionInfo.java b/core/java/android/view/inputmethod/InlineSuggestionInfo.java
new file mode 100644
index 0000000..07fce31
--- /dev/null
+++ b/core/java/android/view/inputmethod/InlineSuggestionInfo.java
@@ -0,0 +1,261 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view.inputmethod;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.Parcelable;
+import android.view.inline.InlinePresentationSpec;
+
+import com.android.internal.util.DataClass;
+
+/**
+ * This class represents the description of an inline suggestion. It contains information to help
+ * the IME to decide where and when to show the suggestions. See {@link InlineSuggestion} for more
+ * information.
+ */
+@DataClass(
+ genEqualsHashCode = true,
+ genToString = true,
+ genHiddenConstDefs = true,
+ genHiddenConstructor = true)
+public final class InlineSuggestionInfo implements Parcelable {
+
+ /**
+ * Suggestion source: the suggestion is made by the user selected autofill service.
+ */
+ public static final @Source String SOURCE_AUTOFILL = "android:autofill";
+ /**
+ * Suggestion source: the suggestion is made by the platform.
+ */
+ public static final @Source String SOURCE_PLATFORM = "android:platform";
+
+ /** The presentation spec to which the inflated suggestion view abides. */
+ private final @NonNull InlinePresentationSpec mPresentationSpec;
+
+ /** The source from which the suggestion is provided. */
+ private final @NonNull @Source String mSource;
+
+ /** Hints for the type of data being suggested. */
+ private final @Nullable String[] mAutofillHints;
+
+
+
+
+ // Code below generated by codegen v1.0.14.
+ //
+ // DO NOT MODIFY!
+ // CHECKSTYLE:OFF Generated code
+ //
+ // To regenerate run:
+ // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/view/inputmethod/InlineSuggestionInfo.java
+ //
+ // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
+ // Settings > Editor > Code Style > Formatter Control
+ //@formatter:off
+
+
+ /** @hide */
+ @android.annotation.StringDef(prefix = "SOURCE_", value = {
+ SOURCE_AUTOFILL,
+ SOURCE_PLATFORM
+ })
+ @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE)
+ @DataClass.Generated.Member
+ public @interface Source {}
+
+ /**
+ * Creates a new InlineSuggestionInfo.
+ *
+ * @param presentationSpec
+ * The presentation spec to which the inflated suggestion view abides.
+ * @param source
+ * The source from which the suggestion is provided.
+ * @param autofillHints
+ * Hints for the type of data being suggested.
+ * @hide
+ */
+ @DataClass.Generated.Member
+ public InlineSuggestionInfo(
+ @NonNull InlinePresentationSpec presentationSpec,
+ @NonNull @Source String source,
+ @Nullable String[] autofillHints) {
+ this.mPresentationSpec = presentationSpec;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mPresentationSpec);
+ this.mSource = source;
+
+ if (!(java.util.Objects.equals(mSource, SOURCE_AUTOFILL))
+ && !(java.util.Objects.equals(mSource, SOURCE_PLATFORM))) {
+ throw new java.lang.IllegalArgumentException(
+ "source was " + mSource + " but must be one of: "
+ + "SOURCE_AUTOFILL(" + SOURCE_AUTOFILL + "), "
+ + "SOURCE_PLATFORM(" + SOURCE_PLATFORM + ")");
+ }
+
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mSource);
+ this.mAutofillHints = autofillHints;
+
+ // onConstructed(); // You can define this method to get a callback
+ }
+
+ /**
+ * The presentation spec to which the inflated suggestion view abides.
+ */
+ @DataClass.Generated.Member
+ public @NonNull InlinePresentationSpec getPresentationSpec() {
+ return mPresentationSpec;
+ }
+
+ /**
+ * The source from which the suggestion is provided.
+ */
+ @DataClass.Generated.Member
+ public @NonNull @Source String getSource() {
+ return mSource;
+ }
+
+ /**
+ * Hints for the type of data being suggested.
+ */
+ @DataClass.Generated.Member
+ public @Nullable String[] getAutofillHints() {
+ return mAutofillHints;
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public String toString() {
+ // You can override field toString logic by defining methods like:
+ // String fieldNameToString() { ... }
+
+ return "InlineSuggestionInfo { " +
+ "presentationSpec = " + mPresentationSpec + ", " +
+ "source = " + mSource + ", " +
+ "autofillHints = " + java.util.Arrays.toString(mAutofillHints) +
+ " }";
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public boolean equals(@Nullable Object o) {
+ // You can override field equality logic by defining either of the methods like:
+ // boolean fieldNameEquals(InlineSuggestionInfo other) { ... }
+ // boolean fieldNameEquals(FieldType otherValue) { ... }
+
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ @SuppressWarnings("unchecked")
+ InlineSuggestionInfo that = (InlineSuggestionInfo) o;
+ //noinspection PointlessBooleanExpression
+ return true
+ && java.util.Objects.equals(mPresentationSpec, that.mPresentationSpec)
+ && java.util.Objects.equals(mSource, that.mSource)
+ && java.util.Arrays.equals(mAutofillHints, that.mAutofillHints);
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public int hashCode() {
+ // You can override field hashCode logic by defining methods like:
+ // int fieldNameHashCode() { ... }
+
+ int _hash = 1;
+ _hash = 31 * _hash + java.util.Objects.hashCode(mPresentationSpec);
+ _hash = 31 * _hash + java.util.Objects.hashCode(mSource);
+ _hash = 31 * _hash + java.util.Arrays.hashCode(mAutofillHints);
+ return _hash;
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public void writeToParcel(@NonNull android.os.Parcel dest, int flags) {
+ // You can override field parcelling by defining methods like:
+ // void parcelFieldName(Parcel dest, int flags) { ... }
+
+ byte flg = 0;
+ if (mAutofillHints != null) flg |= 0x4;
+ dest.writeByte(flg);
+ dest.writeTypedObject(mPresentationSpec, flags);
+ dest.writeString(mSource);
+ if (mAutofillHints != null) dest.writeStringArray(mAutofillHints);
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public int describeContents() { return 0; }
+
+ /** @hide */
+ @SuppressWarnings({"unchecked", "RedundantCast"})
+ @DataClass.Generated.Member
+ /* package-private */ InlineSuggestionInfo(@NonNull android.os.Parcel in) {
+ // You can override field unparcelling by defining methods like:
+ // static FieldType unparcelFieldName(Parcel in) { ... }
+
+ byte flg = in.readByte();
+ InlinePresentationSpec presentationSpec = (InlinePresentationSpec) in.readTypedObject(InlinePresentationSpec.CREATOR);
+ String source = in.readString();
+ String[] autofillHints = (flg & 0x4) == 0 ? null : in.createStringArray();
+
+ this.mPresentationSpec = presentationSpec;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mPresentationSpec);
+ this.mSource = source;
+
+ if (!(java.util.Objects.equals(mSource, SOURCE_AUTOFILL))
+ && !(java.util.Objects.equals(mSource, SOURCE_PLATFORM))) {
+ throw new java.lang.IllegalArgumentException(
+ "source was " + mSource + " but must be one of: "
+ + "SOURCE_AUTOFILL(" + SOURCE_AUTOFILL + "), "
+ + "SOURCE_PLATFORM(" + SOURCE_PLATFORM + ")");
+ }
+
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mSource);
+ this.mAutofillHints = autofillHints;
+
+ // onConstructed(); // You can define this method to get a callback
+ }
+
+ @DataClass.Generated.Member
+ public static final @NonNull Parcelable.Creator<InlineSuggestionInfo> CREATOR
+ = new Parcelable.Creator<InlineSuggestionInfo>() {
+ @Override
+ public InlineSuggestionInfo[] newArray(int size) {
+ return new InlineSuggestionInfo[size];
+ }
+
+ @Override
+ public InlineSuggestionInfo createFromParcel(@NonNull android.os.Parcel in) {
+ return new InlineSuggestionInfo(in);
+ }
+ };
+
+ @DataClass.Generated(
+ time = 1574406074120L,
+ codegenVersion = "1.0.14",
+ sourceFile = "frameworks/base/core/java/android/view/inputmethod/InlineSuggestionInfo.java",
+ inputSignatures = "public static final @android.view.inputmethod.InlineSuggestionInfo.Source java.lang.String SOURCE_AUTOFILL\npublic static final @android.view.inputmethod.InlineSuggestionInfo.Source java.lang.String SOURCE_PLATFORM\nprivate final @android.annotation.NonNull android.view.inline.InlinePresentationSpec mPresentationSpec\nprivate final @android.annotation.NonNull @android.view.inputmethod.InlineSuggestionInfo.Source java.lang.String mSource\nprivate final @android.annotation.Nullable java.lang.String[] mAutofillHints\nclass InlineSuggestionInfo extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genToString=true, genHiddenConstDefs=true, genHiddenConstructor=true)")
+ @Deprecated
+ private void __metadata() {}
+
+
+ //@formatter:on
+ // End of generated code
+
+}
diff --git a/core/java/android/view/inputmethod/InlineSuggestionsRequest.aidl b/core/java/android/view/inputmethod/InlineSuggestionsRequest.aidl
new file mode 100644
index 0000000..5a8abd2
--- /dev/null
+++ b/core/java/android/view/inputmethod/InlineSuggestionsRequest.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view.inputmethod;
+
+parcelable InlineSuggestionsRequest;
diff --git a/core/java/android/view/inputmethod/InlineSuggestionsRequest.java b/core/java/android/view/inputmethod/InlineSuggestionsRequest.java
new file mode 100644
index 0000000..dd609ee
--- /dev/null
+++ b/core/java/android/view/inputmethod/InlineSuggestionsRequest.java
@@ -0,0 +1,261 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view.inputmethod;
+
+import android.annotation.NonNull;
+import android.os.Parcelable;
+import android.view.inline.InlinePresentationSpec;
+
+import com.android.internal.util.DataClass;
+import com.android.internal.util.Preconditions;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * This class represents an inline suggestion request made by one app to get suggestions from the
+ * other source. See {@link InlineSuggestion} for more information.
+ */
+@DataClass(genEqualsHashCode = true, genToString = true, genBuilder = true)
+public final class InlineSuggestionsRequest implements Parcelable {
+
+ /** Constant used to indicate not putting a cap on the number of suggestions to return. */
+ public static final int SUGGESTION_COUNT_UNLIMITED = Integer.MAX_VALUE;
+
+ private final int mMaxSuggestionCount;
+ private final @NonNull List<InlinePresentationSpec> mPresentationSpecs;
+
+ private void onConstructed() {
+ Preconditions.checkState(mMaxSuggestionCount >= mPresentationSpecs.size());
+ }
+
+ private static int defaultMaxSuggestionCount() {
+ return SUGGESTION_COUNT_UNLIMITED;
+ }
+
+ /** @hide */
+ abstract static class BaseBuilder {
+ abstract Builder setPresentationSpecs(@NonNull List<InlinePresentationSpec> value);
+ }
+
+
+
+ // Code below generated by codegen v1.0.14.
+ //
+ // DO NOT MODIFY!
+ // CHECKSTYLE:OFF Generated code
+ //
+ // To regenerate run:
+ // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/view/inputmethod/InlineSuggestionsRequest.java
+ //
+ // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
+ // Settings > Editor > Code Style > Formatter Control
+ //@formatter:off
+
+
+ @DataClass.Generated.Member
+ /* package-private */ InlineSuggestionsRequest(
+ int maxSuggestionCount,
+ @NonNull List<InlinePresentationSpec> presentationSpecs) {
+ this.mMaxSuggestionCount = maxSuggestionCount;
+ this.mPresentationSpecs = presentationSpecs;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mPresentationSpecs);
+
+ onConstructed();
+ }
+
+ @DataClass.Generated.Member
+ public int getMaxSuggestionCount() {
+ return mMaxSuggestionCount;
+ }
+
+ @DataClass.Generated.Member
+ public @NonNull List<InlinePresentationSpec> getPresentationSpecs() {
+ return mPresentationSpecs;
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public String toString() {
+ // You can override field toString logic by defining methods like:
+ // String fieldNameToString() { ... }
+
+ return "InlineSuggestionsRequest { " +
+ "maxSuggestionCount = " + mMaxSuggestionCount + ", " +
+ "presentationSpecs = " + mPresentationSpecs +
+ " }";
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public boolean equals(@android.annotation.Nullable Object o) {
+ // You can override field equality logic by defining either of the methods like:
+ // boolean fieldNameEquals(InlineSuggestionsRequest other) { ... }
+ // boolean fieldNameEquals(FieldType otherValue) { ... }
+
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ @SuppressWarnings("unchecked")
+ InlineSuggestionsRequest that = (InlineSuggestionsRequest) o;
+ //noinspection PointlessBooleanExpression
+ return true
+ && mMaxSuggestionCount == that.mMaxSuggestionCount
+ && java.util.Objects.equals(mPresentationSpecs, that.mPresentationSpecs);
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public int hashCode() {
+ // You can override field hashCode logic by defining methods like:
+ // int fieldNameHashCode() { ... }
+
+ int _hash = 1;
+ _hash = 31 * _hash + mMaxSuggestionCount;
+ _hash = 31 * _hash + java.util.Objects.hashCode(mPresentationSpecs);
+ return _hash;
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public void writeToParcel(@NonNull android.os.Parcel dest, int flags) {
+ // You can override field parcelling by defining methods like:
+ // void parcelFieldName(Parcel dest, int flags) { ... }
+
+ dest.writeInt(mMaxSuggestionCount);
+ dest.writeParcelableList(mPresentationSpecs, flags);
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public int describeContents() { return 0; }
+
+ /** @hide */
+ @SuppressWarnings({"unchecked", "RedundantCast"})
+ @DataClass.Generated.Member
+ /* package-private */ InlineSuggestionsRequest(@NonNull android.os.Parcel in) {
+ // You can override field unparcelling by defining methods like:
+ // static FieldType unparcelFieldName(Parcel in) { ... }
+
+ int maxSuggestionCount = in.readInt();
+ List<InlinePresentationSpec> presentationSpecs = new ArrayList<>();
+ in.readParcelableList(presentationSpecs, InlinePresentationSpec.class.getClassLoader());
+
+ this.mMaxSuggestionCount = maxSuggestionCount;
+ this.mPresentationSpecs = presentationSpecs;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mPresentationSpecs);
+
+ onConstructed();
+ }
+
+ @DataClass.Generated.Member
+ public static final @NonNull Parcelable.Creator<InlineSuggestionsRequest> CREATOR
+ = new Parcelable.Creator<InlineSuggestionsRequest>() {
+ @Override
+ public InlineSuggestionsRequest[] newArray(int size) {
+ return new InlineSuggestionsRequest[size];
+ }
+
+ @Override
+ public InlineSuggestionsRequest createFromParcel(@NonNull android.os.Parcel in) {
+ return new InlineSuggestionsRequest(in);
+ }
+ };
+
+ /**
+ * A builder for {@link InlineSuggestionsRequest}
+ */
+ @SuppressWarnings("WeakerAccess")
+ @DataClass.Generated.Member
+ public static final class Builder extends BaseBuilder {
+
+ private int mMaxSuggestionCount;
+ private @NonNull List<InlinePresentationSpec> mPresentationSpecs;
+
+ private long mBuilderFieldsSet = 0L;
+
+ public Builder(
+ @NonNull List<InlinePresentationSpec> presentationSpecs) {
+ mPresentationSpecs = presentationSpecs;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mPresentationSpecs);
+ }
+
+ @DataClass.Generated.Member
+ public @NonNull Builder setMaxSuggestionCount(int value) {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x1;
+ mMaxSuggestionCount = value;
+ return this;
+ }
+
+ @DataClass.Generated.Member
+ @Override
+ @NonNull Builder setPresentationSpecs(@NonNull List<InlinePresentationSpec> value) {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x2;
+ mPresentationSpecs = value;
+ return this;
+ }
+
+ /** @see #setPresentationSpecs */
+ @DataClass.Generated.Member
+ public @NonNull Builder addPresentationSpecs(@NonNull InlinePresentationSpec value) {
+ // You can refine this method's name by providing item's singular name, e.g.:
+ // @DataClass.PluralOf("item")) mItems = ...
+
+ if (mPresentationSpecs == null) setPresentationSpecs(new ArrayList<>());
+ mPresentationSpecs.add(value);
+ return this;
+ }
+
+ /** Builds the instance. This builder should not be touched after calling this! */
+ public @NonNull InlineSuggestionsRequest build() {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x4; // Mark builder used
+
+ if ((mBuilderFieldsSet & 0x1) == 0) {
+ mMaxSuggestionCount = defaultMaxSuggestionCount();
+ }
+ InlineSuggestionsRequest o = new InlineSuggestionsRequest(
+ mMaxSuggestionCount,
+ mPresentationSpecs);
+ return o;
+ }
+
+ private void checkNotUsed() {
+ if ((mBuilderFieldsSet & 0x4) != 0) {
+ throw new IllegalStateException(
+ "This Builder should not be reused. Use a new Builder instance instead");
+ }
+ }
+ }
+
+ @DataClass.Generated(
+ time = 1574406255024L,
+ codegenVersion = "1.0.14",
+ sourceFile = "frameworks/base/core/java/android/view/inputmethod/InlineSuggestionsRequest.java",
+ inputSignatures = "public static final int SUGGESTION_COUNT_UNLIMITED\nprivate final int mMaxSuggestionCount\nprivate final @android.annotation.NonNull java.util.List<android.view.inline.InlinePresentationSpec> mPresentationSpecs\nprivate void onConstructed()\nprivate static int defaultMaxSuggestionCount()\nclass InlineSuggestionsRequest extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genToString=true, genBuilder=true)\nabstract android.view.inputmethod.InlineSuggestionsRequest.Builder setPresentationSpecs(java.util.List<android.view.inline.InlinePresentationSpec>)\nclass BaseBuilder extends java.lang.Object implements []")
+ @Deprecated
+ private void __metadata() {}
+
+
+ //@formatter:on
+ // End of generated code
+
+}
diff --git a/core/java/android/view/inputmethod/InlineSuggestionsResponse.aidl b/core/java/android/view/inputmethod/InlineSuggestionsResponse.aidl
new file mode 100644
index 0000000..9343fe9
--- /dev/null
+++ b/core/java/android/view/inputmethod/InlineSuggestionsResponse.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view.inputmethod;
+
+parcelable InlineSuggestionsResponse;
diff --git a/core/java/android/view/inputmethod/InlineSuggestionsResponse.java b/core/java/android/view/inputmethod/InlineSuggestionsResponse.java
new file mode 100644
index 0000000..924a5ee
--- /dev/null
+++ b/core/java/android/view/inputmethod/InlineSuggestionsResponse.java
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view.inputmethod;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.Parcelable;
+
+import com.android.internal.util.DataClass;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * This class represents an inline suggestion response. See {@link InlineSuggestion} for more
+ * information.
+ */
+@DataClass(genEqualsHashCode = true, genToString = true, genHiddenConstructor = true)
+public final class InlineSuggestionsResponse implements Parcelable {
+ private final @NonNull List<InlineSuggestion> mInlineSuggestions;
+
+
+
+ // Code below generated by codegen v1.0.14.
+ //
+ // DO NOT MODIFY!
+ // CHECKSTYLE:OFF Generated code
+ //
+ // To regenerate run:
+ // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/view/inputmethod/InlineSuggestionsResponse.java
+ //
+ // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
+ // Settings > Editor > Code Style > Formatter Control
+ //@formatter:off
+
+
+ /**
+ * Creates a new InlineSuggestionsResponse.
+ *
+ * @hide
+ */
+ @DataClass.Generated.Member
+ public InlineSuggestionsResponse(
+ @NonNull List<InlineSuggestion> inlineSuggestions) {
+ this.mInlineSuggestions = inlineSuggestions;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mInlineSuggestions);
+
+ // onConstructed(); // You can define this method to get a callback
+ }
+
+ @DataClass.Generated.Member
+ public @NonNull List<InlineSuggestion> getInlineSuggestions() {
+ return mInlineSuggestions;
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public String toString() {
+ // You can override field toString logic by defining methods like:
+ // String fieldNameToString() { ... }
+
+ return "InlineSuggestionsResponse { " +
+ "inlineSuggestions = " + mInlineSuggestions +
+ " }";
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public boolean equals(@Nullable Object o) {
+ // You can override field equality logic by defining either of the methods like:
+ // boolean fieldNameEquals(InlineSuggestionsResponse other) { ... }
+ // boolean fieldNameEquals(FieldType otherValue) { ... }
+
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ @SuppressWarnings("unchecked")
+ InlineSuggestionsResponse that = (InlineSuggestionsResponse) o;
+ //noinspection PointlessBooleanExpression
+ return true
+ && java.util.Objects.equals(mInlineSuggestions, that.mInlineSuggestions);
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public int hashCode() {
+ // You can override field hashCode logic by defining methods like:
+ // int fieldNameHashCode() { ... }
+
+ int _hash = 1;
+ _hash = 31 * _hash + java.util.Objects.hashCode(mInlineSuggestions);
+ return _hash;
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public void writeToParcel(@NonNull android.os.Parcel dest, int flags) {
+ // You can override field parcelling by defining methods like:
+ // void parcelFieldName(Parcel dest, int flags) { ... }
+
+ dest.writeParcelableList(mInlineSuggestions, flags);
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public int describeContents() { return 0; }
+
+ /** @hide */
+ @SuppressWarnings({"unchecked", "RedundantCast"})
+ @DataClass.Generated.Member
+ /* package-private */ InlineSuggestionsResponse(@NonNull android.os.Parcel in) {
+ // You can override field unparcelling by defining methods like:
+ // static FieldType unparcelFieldName(Parcel in) { ... }
+
+ List<InlineSuggestion> inlineSuggestions = new ArrayList<>();
+ in.readParcelableList(inlineSuggestions, InlineSuggestion.class.getClassLoader());
+
+ this.mInlineSuggestions = inlineSuggestions;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mInlineSuggestions);
+
+ // onConstructed(); // You can define this method to get a callback
+ }
+
+ @DataClass.Generated.Member
+ public static final @NonNull Parcelable.Creator<InlineSuggestionsResponse> CREATOR
+ = new Parcelable.Creator<InlineSuggestionsResponse>() {
+ @Override
+ public InlineSuggestionsResponse[] newArray(int size) {
+ return new InlineSuggestionsResponse[size];
+ }
+
+ @Override
+ public InlineSuggestionsResponse createFromParcel(@NonNull android.os.Parcel in) {
+ return new InlineSuggestionsResponse(in);
+ }
+ };
+
+ @DataClass.Generated(
+ time = 1574406147911L,
+ codegenVersion = "1.0.14",
+ sourceFile = "frameworks/base/core/java/android/view/inputmethod/InlineSuggestionsResponse.java",
+ inputSignatures = "private final @android.annotation.NonNull java.util.List<android.view.inputmethod.InlineSuggestion> mInlineSuggestions\nclass InlineSuggestionsResponse extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genToString=true, genHiddenConstructor=true)")
+ @Deprecated
+ private void __metadata() {}
+
+
+ //@formatter:on
+ // End of generated code
+
+}
diff --git a/core/java/android/widget/ArrayAdapter.java b/core/java/android/widget/ArrayAdapter.java
index 2bf1ba5..f7225d0 100644
--- a/core/java/android/widget/ArrayAdapter.java
+++ b/core/java/android/widget/ArrayAdapter.java
@@ -49,9 +49,6 @@
* To customize what type of view is used for the data object,
* override {@link #getView(int, View, ViewGroup)}
* and inflate a view resource.
- * For a code example, see
- * the <a href="https://github.com/googlesamples/android-CustomChoiceList/#readme">
- * CustomChoiceList</a> sample.
* </p>
* <p>
* For an example of using an array adapter with a ListView, see the
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index 86cec5e..c571737 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -202,6 +202,14 @@
public static final int FLAG_USE_LIGHT_BACKGROUND_LAYOUT = 4;
/**
+ * Used to restrict the views which can be inflated
+ *
+ * @see android.view.LayoutInflater.Filter#onLoadClass(java.lang.Class)
+ */
+ private static final LayoutInflater.Filter INFLATER_FILTER =
+ (clazz) -> clazz.isAnnotationPresent(RemoteViews.RemoteView.class);
+
+ /**
* Application that hosts the remote views.
*
* @hide
@@ -3413,13 +3421,24 @@
// Clone inflater so we load resources from correct context and
// we don't add a filter to the static version returned by getSystemService.
inflater = inflater.cloneInContext(inflationContext);
- inflater.setFilter(this);
+ inflater.setFilter(shouldUseStaticFilter() ? INFLATER_FILTER : this);
View v = inflater.inflate(rv.getLayoutId(), parent, false);
v.setTagInternal(R.id.widget_frame, rv.getLayoutId());
return v;
}
/**
+ * A static filter is much lighter than RemoteViews itself. It's optimized here only for
+ * RemoteVies class. Subclasses should always override this and return true if not overriding
+ * {@link this#onLoadClass(Class)}.
+ *
+ * @hide
+ */
+ protected boolean shouldUseStaticFilter() {
+ return this.getClass().equals(RemoteViews.class);
+ }
+
+ /**
* Implement this interface to receive a callback when
* {@link #applyAsync} or {@link #reapplyAsync} is finished.
* @hide
@@ -3686,11 +3705,15 @@
return (mActions == null) ? 0 : mActions.size();
}
- /* (non-Javadoc)
+ /**
* Used to restrict the views which can be inflated
*
* @see android.view.LayoutInflater.Filter#onLoadClass(java.lang.Class)
+ * @deprecated Used by system to enforce safe inflation of {@link RemoteViews}. Apps should not
+ * override this method. Changing of this method will NOT affect the process where RemoteViews
+ * is rendered.
*/
+ @Deprecated
public boolean onLoadClass(Class clazz) {
return clazz.isAnnotationPresent(RemoteView.class);
}
diff --git a/core/java/com/android/internal/app/TEST_MAPPING b/core/java/com/android/internal/app/TEST_MAPPING
new file mode 100644
index 0000000..373a5d9
--- /dev/null
+++ b/core/java/com/android/internal/app/TEST_MAPPING
@@ -0,0 +1,20 @@
+{
+ "postsubmit": [
+ {
+ "name": "FrameworksCoreTests",
+ "options": [
+ {
+ "include-filter": "com.android.internal.app."
+ },
+
+ // Many tests failing - do not enable for continuous execution
+ {
+ "exclude-filter": "com.android.internal.app.IntentForwarderActivityTest"
+ },
+ {
+ "exclude-filter": "com.android.internal.app.WindowDecorActionBarTest"
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/core/java/com/android/internal/logging/UiEvent.java b/core/java/com/android/internal/logging/UiEvent.java
new file mode 100644
index 0000000..0407b07
--- /dev/null
+++ b/core/java/com/android/internal/logging/UiEvent.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.logging;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+@Retention(SOURCE)
+@Target(FIELD)
+public @interface UiEvent {
+ /** An explanation, suitable for Android analysts, of the UI event that this log represents. */
+ String doc();
+}
diff --git a/core/java/com/android/internal/logging/UiEventLogger.java b/core/java/com/android/internal/logging/UiEventLogger.java
new file mode 100644
index 0000000..cca97f6
--- /dev/null
+++ b/core/java/com/android/internal/logging/UiEventLogger.java
@@ -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.internal.logging;
+
+/**
+ * Logging interface for UI events. Normal implementation is UiEventLoggerImpl.
+ * For testing, use fake implementation UiEventLoggerFake.
+ *
+ * See go/sysui-event-logs and UiEventReported atom in atoms.proto.
+ */
+public interface UiEventLogger {
+ /** Put your Event IDs in enums that implement this interface, and document them using the
+ * UiEventEnum annotation.
+ * Event IDs must be globally unique. This will be enforced by tooling (forthcoming).
+ * OEMs should use event IDs above 100000.
+ */
+ interface UiEventEnum {
+ int getId();
+ }
+ /**
+ * Log a simple event, with no package or instance ID.
+ */
+ void log(UiEventEnum eventID);
+}
diff --git a/core/java/com/android/internal/logging/UiEventLoggerImpl.java b/core/java/com/android/internal/logging/UiEventLoggerImpl.java
new file mode 100644
index 0000000..e64fba2
--- /dev/null
+++ b/core/java/com/android/internal/logging/UiEventLoggerImpl.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.logging;
+
+import android.util.StatsLog;
+
+/**
+ * Standard implementation of UiEventLogger, writing to StatsLog.
+ *
+ * See UiEventReported atom in atoms.proto for more context.
+ */
+public class UiEventLoggerImpl implements UiEventLogger {
+ /**
+ * Log a simple event, with no package or instance ID.
+ */
+ @Override
+ public void log(UiEventEnum event) {
+ final int eventID = event.getId();
+ if (eventID > 0) {
+ StatsLog.write(StatsLog.UI_EVENT_REPORTED, eventID, 0, null);
+ }
+ }
+}
diff --git a/core/java/com/android/internal/logging/testing/UiEventLoggerFake.java b/core/java/com/android/internal/logging/testing/UiEventLoggerFake.java
new file mode 100644
index 0000000..92e9bbb
--- /dev/null
+++ b/core/java/com/android/internal/logging/testing/UiEventLoggerFake.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.logging.testing;
+
+import com.android.internal.logging.UiEventLogger;
+
+import java.util.LinkedList;
+import java.util.Queue;
+
+/**
+ * Fake logger that queues up logged events for inspection.
+ *
+ * @hide.
+ */
+public class UiEventLoggerFake implements UiEventLogger {
+ /**
+ * Immutable data class used to record fake log events.
+ */
+ public class FakeUiEvent {
+ public final int eventId;
+ public final int uid;
+ public final String packageName;
+
+ public FakeUiEvent(int eventId, int uid, String packageName) {
+ this.eventId = eventId;
+ this.uid = uid;
+ this.packageName = packageName;
+ }
+ }
+
+ private Queue<FakeUiEvent> mLogs = new LinkedList<FakeUiEvent>();
+
+ @Override
+ public void log(UiEventEnum event) {
+ final int eventId = event.getId();
+ if (eventId > 0) {
+ mLogs.offer(new FakeUiEvent(eventId, 0, null));
+ }
+ }
+
+ public Queue<FakeUiEvent> getLogs() {
+ return mLogs;
+ }
+}
diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java
index 227ef28..764d4a59 100644
--- a/core/java/com/android/internal/policy/PhoneWindow.java
+++ b/core/java/com/android/internal/policy/PhoneWindow.java
@@ -3109,8 +3109,9 @@
// On TVs, if the app doesn't implement search, we want to launch assist.
Bundle args = new Bundle();
args.putInt(Intent.EXTRA_ASSIST_INPUT_DEVICE_ID, event.getDeviceId());
- return ((SearchManager)getContext().getSystemService(Context.SEARCH_SERVICE))
- .launchLegacyAssist(null, getContext().getUserId(), args);
+ ((SearchManager) getContext().getSystemService(Context.SEARCH_SERVICE))
+ .launchAssist(args);
+ return true;
}
return result;
}
diff --git a/core/java/com/android/internal/util/function/pooled/PooledLambda.java b/core/java/com/android/internal/util/function/pooled/PooledLambda.java
index d32ff06..a60cc0f 100755
--- a/core/java/com/android/internal/util/function/pooled/PooledLambda.java
+++ b/core/java/com/android/internal/util/function/pooled/PooledLambda.java
@@ -383,7 +383,7 @@
QuadPredicate<? super A, ? super B, ? super C, ? super D> function,
ArgumentPlaceholder<A> arg1, B arg2, C arg3, D arg4) {
return acquire(PooledLambdaImpl.sPool,
- function, 3, 1, ReturnType.BOOLEAN, arg1, arg2, arg3, arg4, null, null, null, null,
+ function, 4, 1, ReturnType.BOOLEAN, arg1, arg2, arg3, arg4, null, null, null, null,
null, null, null);
}
@@ -404,7 +404,7 @@
QuintPredicate<? super A, ? super B, ? super C, ? super D, ? super E> function,
ArgumentPlaceholder<A> arg1, B arg2, C arg3, D arg4, E arg5) {
return acquire(PooledLambdaImpl.sPool,
- function, 3, 1, ReturnType.BOOLEAN, arg1, arg2, arg3, arg4, arg5, null, null, null,
+ function, 5, 1, ReturnType.BOOLEAN, arg1, arg2, arg3, arg4, arg5, null, null, null,
null, null, null);
}
diff --git a/core/java/com/android/internal/view/IInlineSuggestionsRequestCallback.aidl b/core/java/com/android/internal/view/IInlineSuggestionsRequestCallback.aidl
new file mode 100644
index 0000000..6b54910
--- /dev/null
+++ b/core/java/com/android/internal/view/IInlineSuggestionsRequestCallback.aidl
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.view;
+
+import android.view.inputmethod.InlineSuggestionsRequest;
+
+import com.android.internal.view.IInlineSuggestionsResponseCallback;
+
+/**
+ * Binder interface for the IME service to send an inline suggestion request to the system.
+ * {@hide}
+ */
+oneway interface IInlineSuggestionsRequestCallback {
+ void onInlineSuggestionsUnsupported();
+ void onInlineSuggestionsRequest(in InlineSuggestionsRequest request,
+ in IInlineSuggestionsResponseCallback callback);
+}
diff --git a/core/java/com/android/internal/view/IInlineSuggestionsResponseCallback.aidl b/core/java/com/android/internal/view/IInlineSuggestionsResponseCallback.aidl
new file mode 100644
index 0000000..0f93b8e
--- /dev/null
+++ b/core/java/com/android/internal/view/IInlineSuggestionsResponseCallback.aidl
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.view;
+
+import android.view.inputmethod.InlineSuggestionsResponse;
+
+/**
+ * Binder interface for the IME service to receive an inline suggestion response from the system.
+ * {@hide}
+ */
+oneway interface IInlineSuggestionsResponseCallback {
+ void onInlineSuggestionsResponse(in InlineSuggestionsResponse response);
+}
diff --git a/core/java/com/android/internal/view/inline/IInlineContentCallback.aidl b/core/java/com/android/internal/view/inline/IInlineContentCallback.aidl
new file mode 100644
index 0000000..8cc49ca
--- /dev/null
+++ b/core/java/com/android/internal/view/inline/IInlineContentCallback.aidl
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.view.inline;
+
+import android.view.SurfaceControl;
+
+/**
+ * Binder interface to send the inline content from one process to the other.
+ * {@hide}
+ */
+oneway interface IInlineContentCallback {
+ void onContent(in SurfaceControl content);
+}
diff --git a/core/java/com/android/internal/view/inline/IInlineContentProvider.aidl b/core/java/com/android/internal/view/inline/IInlineContentProvider.aidl
new file mode 100644
index 0000000..08a349c
--- /dev/null
+++ b/core/java/com/android/internal/view/inline/IInlineContentProvider.aidl
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.view.inline;
+
+import com.android.internal.view.inline.IInlineContentCallback;
+
+/**
+ * Binder interface for a process to request the inline content from the other process.
+ * {@hide}
+ */
+oneway interface IInlineContentProvider {
+ void provideContent(int width, int height, in IInlineContentCallback callback);
+}
diff --git a/core/jni/Android.bp b/core/jni/Android.bp
index ea10949..51f8fcc 100644
--- a/core/jni/Android.bp
+++ b/core/jni/Android.bp
@@ -125,6 +125,7 @@
"android_text_Hyphenator.cpp",
"android_os_Debug.cpp",
"android_os_GraphicsEnvironment.cpp",
+ "android_os_HidlMemory.cpp",
"android_os_HidlSupport.cpp",
"android_os_HwBinder.cpp",
"android_os_HwBlob.cpp",
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 32d62fe..378e125 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -147,6 +147,7 @@
extern int register_android_os_Trace(JNIEnv* env);
extern int register_android_os_FileObserver(JNIEnv *env);
extern int register_android_os_UEventObserver(JNIEnv* env);
+extern int register_android_os_HidlMemory(JNIEnv* env);
extern int register_android_os_MemoryFile(JNIEnv* env);
extern int register_android_os_SharedMemory(JNIEnv* env);
extern int register_android_net_LocalSocketImpl(JNIEnv* env);
@@ -1432,6 +1433,7 @@
REG_JNI(register_android_os_SystemProperties),
REG_JNI(register_android_os_Binder),
REG_JNI(register_android_os_Parcel),
+ REG_JNI(register_android_os_HidlMemory),
REG_JNI(register_android_os_HidlSupport),
REG_JNI(register_android_os_HwBinder),
REG_JNI(register_android_os_HwBlob),
diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp
index 0487e13..2dec4b3 100755
--- a/core/jni/android/graphics/Bitmap.cpp
+++ b/core/jni/android/graphics/Bitmap.cpp
@@ -223,97 +223,11 @@
bitmap->getSkBitmap(outBitmap);
}
-Bitmap& toBitmap(JNIEnv* env, jobject bitmap) {
- SkASSERT(env);
- SkASSERT(bitmap);
- SkASSERT(env->IsInstanceOf(bitmap, gBitmap_class));
- jlong bitmapHandle = env->GetLongField(bitmap, gBitmap_nativePtr);
- LocalScopedBitmap localBitmap(bitmapHandle);
- return localBitmap->bitmap();
-}
-
Bitmap& toBitmap(jlong bitmapHandle) {
LocalScopedBitmap localBitmap(bitmapHandle);
return localBitmap->bitmap();
}
-void imageInfo(JNIEnv* env, jobject bitmap, AndroidBitmapInfo* info) {
- jlong bitmapHandle = env->GetLongField(bitmap, gBitmap_nativePtr);
- LocalScopedBitmap localBitmap(bitmapHandle);
-
- const SkImageInfo& imageInfo = localBitmap->info();
- info->width = imageInfo.width();
- info->height = imageInfo.height();
- info->stride = localBitmap->rowBytes();
- info->flags = 0;
- switch (imageInfo.colorType()) {
- case kN32_SkColorType:
- info->format = ANDROID_BITMAP_FORMAT_RGBA_8888;
- break;
- case kRGB_565_SkColorType:
- info->format = ANDROID_BITMAP_FORMAT_RGB_565;
- break;
- case kARGB_4444_SkColorType:
- info->format = ANDROID_BITMAP_FORMAT_RGBA_4444;
- break;
- case kAlpha_8_SkColorType:
- info->format = ANDROID_BITMAP_FORMAT_A_8;
- break;
- case kRGBA_F16_SkColorType:
- info->format = ANDROID_BITMAP_FORMAT_RGBA_F16;
- break;
- default:
- info->format = ANDROID_BITMAP_FORMAT_NONE;
- break;
- }
- switch (imageInfo.alphaType()) {
- case kUnknown_SkAlphaType:
- LOG_ALWAYS_FATAL("Bitmap has no alpha type");
- break;
- case kOpaque_SkAlphaType:
- info->flags |= ANDROID_BITMAP_FLAGS_ALPHA_OPAQUE;
- break;
- case kPremul_SkAlphaType:
- info->flags |= ANDROID_BITMAP_FLAGS_ALPHA_PREMUL;
- break;
- case kUnpremul_SkAlphaType:
- info->flags |= ANDROID_BITMAP_FLAGS_ALPHA_UNPREMUL;
- break;
- }
-}
-
-void* lockPixels(JNIEnv* env, jobject bitmap) {
- SkASSERT(env);
- SkASSERT(bitmap);
- SkASSERT(env->IsInstanceOf(bitmap, gBitmap_class));
- jlong bitmapHandle = env->GetLongField(bitmap, gBitmap_nativePtr);
-
- LocalScopedBitmap localBitmap(bitmapHandle);
- if (!localBitmap->valid()) return nullptr;
-
- SkPixelRef& pixelRef = localBitmap->bitmap();
- if (!pixelRef.pixels()) {
- return nullptr;
- }
- pixelRef.ref();
- return pixelRef.pixels();
-}
-
-bool unlockPixels(JNIEnv* env, jobject bitmap) {
- SkASSERT(env);
- SkASSERT(bitmap);
- SkASSERT(env->IsInstanceOf(bitmap, gBitmap_class));
- jlong bitmapHandle = env->GetLongField(bitmap, gBitmap_nativePtr);
-
- LocalScopedBitmap localBitmap(bitmapHandle);
- if (!localBitmap->valid()) return false;
-
- SkPixelRef& pixelRef = localBitmap->bitmap();
- pixelRef.notifyPixelsChanged();
- pixelRef.unref();
- return true;
-}
-
} // namespace bitmap
} // namespace android
@@ -321,6 +235,27 @@
using namespace android;
using namespace android::bitmap;
+Bitmap* GraphicsJNI::getNativeBitmap(JNIEnv* env, jobject bitmap) {
+ SkASSERT(env);
+ SkASSERT(bitmap);
+ SkASSERT(env->IsInstanceOf(bitmap, gBitmap_class));
+ jlong bitmapHandle = env->GetLongField(bitmap, gBitmap_nativePtr);
+ LocalScopedBitmap localBitmap(bitmapHandle);
+ return localBitmap.valid() ? &localBitmap->bitmap() : nullptr;
+}
+
+SkImageInfo GraphicsJNI::getBitmapInfo(JNIEnv* env, jobject bitmap, uint32_t* outRowBytes) {
+ SkASSERT(env);
+ SkASSERT(bitmap);
+ SkASSERT(env->IsInstanceOf(bitmap, gBitmap_class));
+ jlong bitmapHandle = env->GetLongField(bitmap, gBitmap_nativePtr);
+ LocalScopedBitmap localBitmap(bitmapHandle);
+ if (outRowBytes) {
+ *outRowBytes = localBitmap->rowBytes();
+ }
+ return localBitmap->info();
+}
+
bool GraphicsJNI::SetPixels(JNIEnv* env, jintArray srcColors, int srcOffset, int srcStride,
int x, int y, int width, int height, SkBitmap* dstBitmap) {
const jint* array = env->GetIntArrayElements(srcColors, NULL);
diff --git a/core/jni/android/graphics/Bitmap.h b/core/jni/android/graphics/Bitmap.h
index 59adbb2..73eca3a 100644
--- a/core/jni/android/graphics/Bitmap.h
+++ b/core/jni/android/graphics/Bitmap.h
@@ -38,17 +38,8 @@
int bitmapCreateFlags, jbyteArray ninePatchChunk = nullptr,
jobject ninePatchInsets = nullptr, int density = -1);
-
-Bitmap& toBitmap(JNIEnv* env, jobject bitmap);
Bitmap& toBitmap(jlong bitmapHandle);
-// NDK access
-void imageInfo(JNIEnv* env, jobject bitmap, AndroidBitmapInfo* info);
-// Returns a pointer to the pixels or nullptr if the bitmap is not valid
-void* lockPixels(JNIEnv* env, jobject bitmap);
-// Returns true if unlocked, false if the bitmap is no longer valid (destroyed)
-bool unlockPixels(JNIEnv* env, jobject bitmap);
-
/** Reinitialize a bitmap. bitmap must already have its SkAlphaType set in
sync with isPremultiplied
*/
diff --git a/core/jni/android/graphics/Graphics.cpp b/core/jni/android/graphics/Graphics.cpp
index bc1cc09..aa209cb 100644
--- a/core/jni/android/graphics/Graphics.cpp
+++ b/core/jni/android/graphics/Graphics.cpp
@@ -342,10 +342,6 @@
return static_cast<SkColorType>(gConfig2ColorType[legacyConfig]);
}
-void GraphicsJNI::getSkBitmap(JNIEnv* env, jobject bitmap, SkBitmap* outBitmap) {
- bitmap::toBitmap(env, bitmap).getSkBitmap(outBitmap);
-}
-
AndroidBitmapFormat GraphicsJNI::getFormatFromConfig(JNIEnv* env, jobject jconfig) {
ALOG_ASSERT(env);
if (NULL == jconfig) {
diff --git a/core/jni/android/graphics/GraphicsJNI.h b/core/jni/android/graphics/GraphicsJNI.h
index 6e7d9e7..99034ed 100644
--- a/core/jni/android/graphics/GraphicsJNI.h
+++ b/core/jni/android/graphics/GraphicsJNI.h
@@ -61,7 +61,8 @@
static void point_to_jpointf(const SkPoint& point, JNIEnv*, jobject jpointf);
static android::Canvas* getNativeCanvas(JNIEnv*, jobject canvas);
- static void getSkBitmap(JNIEnv*, jobject bitmap, SkBitmap* outBitmap);
+ static android::Bitmap* getNativeBitmap(JNIEnv*, jobject bitmap);
+ static SkImageInfo getBitmapInfo(JNIEnv*, jobject bitmap, uint32_t* outRowBytes);
static SkRegion* getNativeRegion(JNIEnv*, jobject region);
/*
diff --git a/core/jni/android/graphics/apex/android_bitmap.cpp b/core/jni/android/graphics/apex/android_bitmap.cpp
index a328def..90cc986 100644
--- a/core/jni/android/graphics/apex/android_bitmap.cpp
+++ b/core/jni/android/graphics/apex/android_bitmap.cpp
@@ -14,19 +14,25 @@
* limitations under the License.
*/
+#define LOG_TAG "Bitmap"
+#include <log/log.h>
+
#include "android/graphics/bitmap.h"
-#include "Bitmap.h"
#include "TypeCast.h"
#include "GraphicsJNI.h"
+#include <GraphicsJNI.h>
#include <hwui/Bitmap.h>
using namespace android;
ABitmap* ABitmap_acquireBitmapFromJava(JNIEnv* env, jobject bitmapObj) {
- Bitmap& bitmap = android::bitmap::toBitmap(env, bitmapObj);
- bitmap.ref();
- return TypeCast::toABitmap(&bitmap);
+ Bitmap* bitmap = GraphicsJNI::getNativeBitmap(env, bitmapObj);
+ if (bitmap) {
+ bitmap->ref();
+ return TypeCast::toABitmap(bitmap);
+ }
+ return nullptr;
}
void ABitmap_acquireRef(ABitmap* bitmap) {
@@ -37,8 +43,8 @@
SkSafeUnref(TypeCast::toBitmap(bitmap));
}
-static AndroidBitmapFormat getFormat(Bitmap* bitmap) {
- switch (bitmap->colorType()) {
+static AndroidBitmapFormat getFormat(const SkImageInfo& info) {
+ switch (info.colorType()) {
case kN32_SkColorType:
return ANDROID_BITMAP_FORMAT_RGBA_8888;
case kRGB_565_SkColorType:
@@ -71,6 +77,20 @@
}
}
+static uint32_t getInfoFlags(const SkImageInfo& info) {
+ switch (info.alphaType()) {
+ case kUnknown_SkAlphaType:
+ LOG_ALWAYS_FATAL("Bitmap has no alpha type");
+ break;
+ case kOpaque_SkAlphaType:
+ return ANDROID_BITMAP_FLAGS_ALPHA_OPAQUE;
+ case kPremul_SkAlphaType:
+ return ANDROID_BITMAP_FLAGS_ALPHA_PREMUL;
+ case kUnpremul_SkAlphaType:
+ return ANDROID_BITMAP_FLAGS_ALPHA_UNPREMUL;
+ }
+}
+
ABitmap* ABitmap_copy(ABitmap* srcBitmapHandle, AndroidBitmapFormat dstFormat) {
SkColorType dstColorType = getColorType(dstFormat);
if (srcBitmapHandle && dstColorType != kUnknown_SkColorType) {
@@ -87,15 +107,25 @@
return nullptr;
}
+static AndroidBitmapInfo getInfo(const SkImageInfo& imageInfo, uint32_t rowBytes) {
+ AndroidBitmapInfo info;
+ info.width = imageInfo.width();
+ info.height = imageInfo.height();
+ info.stride = rowBytes;
+ info.format = getFormat(imageInfo);
+ info.flags = getInfoFlags(imageInfo);
+ return info;
+}
+
AndroidBitmapInfo ABitmap_getInfo(ABitmap* bitmapHandle) {
Bitmap* bitmap = TypeCast::toBitmap(bitmapHandle);
+ return getInfo(bitmap->info(), bitmap->rowBytes());
+}
- AndroidBitmapInfo info;
- info.width = bitmap->width();
- info.height = bitmap->height();
- info.stride = bitmap->rowBytes();
- info.format = getFormat(bitmap);
- return info;
+AndroidBitmapInfo ABitmap_getInfoFromJava(JNIEnv* env, jobject bitmapObj) {
+ uint32_t rowBytes = 0;
+ SkImageInfo imageInfo = GraphicsJNI::getBitmapInfo(env, bitmapObj, &rowBytes);
+ return getInfo(imageInfo, rowBytes);
}
void* ABitmap_getPixels(ABitmap* bitmapHandle) {
@@ -107,9 +137,17 @@
}
AndroidBitmapFormat ABitmapConfig_getFormatFromConfig(JNIEnv* env, jobject bitmapConfigObj) {
- return GraphicsJNI::getFormatFromConfig(env, bitmapConfigObj);
+ return GraphicsJNI::getFormatFromConfig(env, bitmapConfigObj);
}
jobject ABitmapConfig_getConfigFromFormat(JNIEnv* env, AndroidBitmapFormat format) {
- return GraphicsJNI::getConfigFromFormat(env, format);
+ return GraphicsJNI::getConfigFromFormat(env, format);
+}
+
+void ABitmap_notifyPixelsChanged(ABitmap* bitmapHandle) {
+ Bitmap* bitmap = TypeCast::toBitmap(bitmapHandle);
+ if (bitmap->isImmutable()) {
+ ALOGE("Attempting to modify an immutable Bitmap!");
+ }
+ return bitmap->notifyPixelsChanged();
}
diff --git a/core/jni/android/graphics/apex/include/android/graphics/bitmap.h b/core/jni/android/graphics/apex/include/android/graphics/bitmap.h
index dea5517..f231eed 100644
--- a/core/jni/android/graphics/apex/include/android/graphics/bitmap.h
+++ b/core/jni/android/graphics/apex/include/android/graphics/bitmap.h
@@ -27,6 +27,20 @@
*/
typedef struct ABitmap ABitmap;
+/**
+ * Retrieve bitmapInfo for the provided java bitmap even if it has been recycled. In the case of a
+ * recycled bitmap the values contained in the bitmap before it was recycled are returned.
+ *
+ * NOTE: This API does not need to remain as an APEX API if/when we pull libjnigraphics into the
+ * UI module.
+ */
+AndroidBitmapInfo ABitmap_getInfoFromJava(JNIEnv* env, jobject bitmapObj);
+
+/**
+ *
+ * @return ptr to an opaque handle to the native bitmap or null if the java bitmap has been recycled
+ * or does not exist.
+ */
ABitmap* ABitmap_acquireBitmapFromJava(JNIEnv* env, jobject bitmapObj);
ABitmap* ABitmap_copy(ABitmap* srcBitmap, AndroidBitmapFormat dstFormat);
@@ -37,6 +51,7 @@
AndroidBitmapInfo ABitmap_getInfo(ABitmap* bitmap);
void* ABitmap_getPixels(ABitmap* bitmap);
+void ABitmap_notifyPixelsChanged(ABitmap* bitmap);
AndroidBitmapFormat ABitmapConfig_getFormatFromConfig(JNIEnv* env, jobject bitmapConfigObj);
jobject ABitmapConfig_getConfigFromFormat(JNIEnv* env, AndroidBitmapFormat format);
@@ -88,10 +103,12 @@
mBitmap = nullptr;
}
- const ABitmap* get() const { return mBitmap; }
+ ABitmap* get() const { return mBitmap; }
AndroidBitmapInfo getInfo() const { return ABitmap_getInfo(mBitmap); }
void* getPixels() const { return ABitmap_getPixels(mBitmap); }
+ void notifyPixelsChanged() const { ABitmap_notifyPixelsChanged(mBitmap); }
+
private:
// takes ownership of the provided ABitmap
Bitmap(ABitmap* bitmap) : mBitmap(bitmap) {}
diff --git a/core/jni/android_os_HidlMemory.cpp b/core/jni/android_os_HidlMemory.cpp
new file mode 100644
index 0000000..69e4818
--- /dev/null
+++ b/core/jni/android_os_HidlMemory.cpp
@@ -0,0 +1,162 @@
+/*
+ * 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.
+ */
+
+#include "android_os_HidlMemory.h"
+#include "core_jni_helpers.h"
+#include "android_os_NativeHandle.h"
+
+#define PACKAGE_PATH "android/os"
+#define CLASS_NAME "HidlMemory"
+#define CLASS_PATH PACKAGE_PATH "/" CLASS_NAME
+
+namespace android {
+
+namespace {
+
+static struct {
+ jclass clazz;
+ jfieldID nativeContext; // long
+ jmethodID constructor; // HidlMemory(String, long, NativeHandle)
+ jmethodID getName; // String HidlMemory.getName()
+ jmethodID getSize; // int HidlMemory.getSize()
+ jmethodID getHandle; // NativeHandle HidlMemory.getHandle()
+} gFields;
+
+std::string stringFromJava(JNIEnv* env, jstring jstr) {
+ ScopedUtfChars s(env, jstr);
+ return s.c_str();
+}
+
+jstring stringToJava(JNIEnv* env, const std::string& cstr) {
+ return env->NewStringUTF(cstr.c_str());
+}
+
+static void nativeFinalize(JNIEnv* env, jobject jobj) {
+ jlong jNativeContext = env->GetLongField(jobj, gFields.nativeContext);
+ JHidlMemory* native = reinterpret_cast<JHidlMemory*>(jNativeContext);
+ delete native;
+}
+
+static JNINativeMethod gMethods[] = {
+ {"nativeFinalize", "()V", (void*) nativeFinalize},
+};
+
+} // namespace
+
+JHidlMemory::~JHidlMemory() {
+ if (mObj) {
+ // Must manually delete the underlying handle - hidl_memory doesn't own
+ // it.
+ native_handle_delete(const_cast<native_handle_t*>(mObj->handle()));
+ }
+}
+
+/* static */ const hardware::hidl_memory* JHidlMemory::fromJava(JNIEnv* env,
+ jobject jobj) {
+ // Try to get the result from cache.
+ env->MonitorEnter(jobj);
+ JHidlMemory* obj = getNativeContext(env, jobj);
+ if (!obj->mObj) {
+ // Create and cache.
+ obj->mObj = javaToNative(env, jobj);
+ }
+ env->MonitorExit(jobj);
+ return obj->mObj.get();
+}
+
+/* static */ jobject JHidlMemory::toJava(JNIEnv* env,
+ const hardware::hidl_memory& cobj) {
+ if (cobj.size() > std::numeric_limits<jlong>::max()) {
+ return nullptr;
+ }
+ jstring jname = stringToJava(env, cobj.name());
+ jlong jsize = static_cast<jlong>(cobj.size());
+ jobject jhandle =
+ JNativeHandle::MakeJavaNativeHandleObj(env, cobj.handle());
+
+ // We're sharing the handle of cobj, so the Java instance doesn't own it.
+ return env->NewObject(gFields.clazz,
+ gFields.constructor,
+ jname,
+ jsize,
+ jhandle,
+ false);
+}
+
+/* static */ std::unique_ptr<hardware::hidl_memory> JHidlMemory::javaToNative(
+ JNIEnv* env,
+ jobject jobj) {
+ jstring jname =
+ static_cast<jstring>(env->CallObjectMethod(jobj, gFields.getName));
+ jlong jsize = env->CallLongMethod(jobj, gFields.getSize);
+ jobject jhandle = env->CallObjectMethod(jobj, gFields.getHandle);
+
+ if (jsize > std::numeric_limits<size_t>::max()) {
+ return nullptr;
+ }
+
+ std::string cname = stringFromJava(env, jname);
+ size_t csize = jsize;
+ // We created the handle here, we're responsible to call
+ // native_handle_delete() on it. However, we don't assume ownership of the
+ // underlying fd, so we shouldn't call native_handle_close() on it.
+ native_handle_t* chandle = JNativeHandle::MakeCppNativeHandle(env, jhandle,
+ nullptr);
+ // hidl_memory doesn't take ownership of the handle here, so won't delete
+ // or close it.
+ return std::make_unique<hardware::hidl_memory>(cname, chandle, csize);
+}
+
+/* static */ JHidlMemory* JHidlMemory::getNativeContext(JNIEnv* env,
+ jobject jobj) {
+ env->MonitorEnter(jobj);
+ jlong jNativeContext = env->GetLongField(jobj, gFields.nativeContext);
+ JHidlMemory* native = reinterpret_cast<JHidlMemory*>(jNativeContext);
+ if (!native) {
+ native = new JHidlMemory();
+ env->SetLongField(jobj,
+ gFields.nativeContext,
+ reinterpret_cast<jlong>(native));
+ }
+ env->MonitorExit(jobj);
+ return native;
+}
+
+int register_android_os_HidlMemory(JNIEnv* env) {
+ jclass clazz = FindClassOrDie(env, CLASS_PATH);
+ gFields.clazz = MakeGlobalRefOrDie(env, clazz);
+
+ gFields.nativeContext = GetFieldIDOrDie(env, clazz, "mNativeContext", "J");
+
+ gFields.constructor = GetMethodIDOrDie(env,
+ clazz,
+ "<init>",
+ "(Ljava/lang/String;JL" PACKAGE_PATH "/NativeHandle;)V");
+ gFields.getName =
+ GetMethodIDOrDie(env, clazz, "getName", "()Ljava/lang/String;");
+ gFields.getSize = GetMethodIDOrDie(env, clazz, "getSize", "()J");
+ gFields.getHandle = GetMethodIDOrDie(env,
+ clazz,
+ "getHandle",
+ "()L" PACKAGE_PATH "/NativeHandle;");
+
+ RegisterMethodsOrDie(env, CLASS_PATH, gMethods, NELEM(gMethods));
+
+ return 0;
+}
+
+} // namespace android
+
diff --git a/core/jni/android_os_HidlMemory.h b/core/jni/android_os_HidlMemory.h
new file mode 100644
index 0000000..993a132
--- /dev/null
+++ b/core/jni/android_os_HidlMemory.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_OS_HIDL_MEMORY_H
+#define ANDROID_OS_HIDL_MEMORY_H
+
+#include <jni.h>
+#include <hidl/HidlSupport.h>
+
+namespace android {
+
+// A utility class for handling the android.os.HidlMemory class from JNI code.
+class JHidlMemory final {
+ public:
+ // Convert an android.os.HidlMemory object to its C++ counterpart,
+ // hardware::hidl_memory.
+ // No duplication of file descriptors is performed.
+ // The returned reference is owned by the underlying Java object.
+ // Returns nullptr if conversion cannot be done.
+ static const hardware::hidl_memory* fromJava(JNIEnv* env,
+ jobject jobj);
+
+ // Convert a hardware::hidl_memory object to its Java counterpart,
+ // android.os.HidlMemory.
+ // No duplication of file descriptors is performed.
+ // Returns nullptr if conversion cannot be done.
+ static jobject toJava(JNIEnv* env,
+ const hardware::hidl_memory& cobj);
+
+ ~JHidlMemory();
+
+ private:
+ // We store an instance of type JHidlMemory attached to every Java object
+ // of type HidlMemory, for holding any native context we need. This instance
+ // will get deleted when finalize() is called on the Java object.
+ // This method either extracts the native object from the Java object, or
+ // attached a new one if it doesn't yet exist.
+ static JHidlMemory* getNativeContext(JNIEnv* env, jobject obj);
+
+ // Convert an android.os.HidlMemory object to its C++ counterpart,
+ // hardware::hidl_memory.
+ // No duplication of file descriptors is performed.
+ // IMPORTANT: caller is responsible to native_handle_delete() the handle of the
+ // returned object. This is due to an underlying limitation of the hidl_handle
+ // type, where ownership of the handle implies ownership of the fd and we don't
+ // want the latter.
+ // Returns nullptr if conversion cannot be done.
+ static std::unique_ptr<hardware::hidl_memory> javaToNative(JNIEnv* env,
+ jobject jobj);
+
+ std::unique_ptr<hardware::hidl_memory> mObj;
+};
+
+int register_android_os_HidlMemory(JNIEnv* env);
+
+} // namespace android
+
+#endif //ANDROID_OS_HIDL_MEMORY_H
diff --git a/core/jni/android_os_HwBlob.cpp b/core/jni/android_os_HwBlob.cpp
index e5b72ca..0fb2911 100644
--- a/core/jni/android_os_HwBlob.cpp
+++ b/core/jni/android_os_HwBlob.cpp
@@ -340,6 +340,14 @@
return env->NewStringUTF(s->c_str());
}
+static jlong JHwBlob_native_getFieldHandle(JNIEnv* env,
+ jobject thiz,
+ jlong offset) {
+ sp<JHwBlob> blob = JHwBlob::GetNativeContext(env, thiz);
+
+ return reinterpret_cast<jlong>(blob->data()) + offset;
+}
+
#define DEFINE_BLOB_ARRAY_COPIER(Suffix,Type,NewType) \
static void JHwBlob_native_copyTo ## Suffix ## Array( \
JNIEnv *env, \
@@ -593,6 +601,7 @@
{ "getFloat", "(J)F", (void *)JHwBlob_native_getFloat },
{ "getDouble", "(J)D", (void *)JHwBlob_native_getDouble },
{ "getString", "(J)Ljava/lang/String;", (void *)JHwBlob_native_getString },
+ { "getFieldHandle", "(J)J", (void*) JHwBlob_native_getFieldHandle},
{ "copyToBoolArray", "(J[ZI)V", (void *)JHwBlob_native_copyToBoolArray },
{ "copyToInt8Array", "(J[BI)V", (void *)JHwBlob_native_copyToInt8Array },
diff --git a/core/jni/android_os_HwParcel.cpp b/core/jni/android_os_HwParcel.cpp
index f437a78..151dbfc 100644
--- a/core/jni/android_os_HwParcel.cpp
+++ b/core/jni/android_os_HwParcel.cpp
@@ -20,6 +20,7 @@
#include "android_os_HwParcel.h"
+#include "android_os_HidlMemory.h"
#include "android_os_HwBinder.h"
#include "android_os_HwBlob.h"
#include "android_os_NativeHandle.h"
@@ -27,6 +28,8 @@
#include <nativehelper/JNIHelp.h>
#include <android_runtime/AndroidRuntime.h>
+#include <hidl/HidlBinderSupport.h>
+#include <hidl/HidlSupport.h>
#include <hidl/HidlTransportSupport.h>
#include <hidl/Status.h>
#include <nativehelper/ScopedLocalRef.h>
@@ -650,6 +653,36 @@
signalExceptionForError(env, err);
}
+static void JHwParcel_native_writeHidlMemory(
+ JNIEnv *env, jobject thiz, jobject jmem) {
+
+ if (jmem == nullptr) {
+ jniThrowException(env, "java/lang/NullPointerException", nullptr);
+ return;
+ }
+
+ status_t err = OK;
+
+ // Convert the Java object to its C++ counterpart.
+ const hardware::hidl_memory* cmem = JHidlMemory::fromJava(env, jmem);
+ if (cmem == nullptr) {
+ err = BAD_VALUE;
+ }
+
+ if (err == OK) {
+ // Write it to the parcel.
+ hardware::Parcel* parcel =
+ JHwParcel::GetNativeContext(env, thiz)->getParcel();
+
+ size_t parentHandle;
+ err = parcel->writeBuffer(cmem, sizeof(*cmem), &parentHandle);
+ if (err == OK) {
+ err = hardware::writeEmbeddedToParcel(*cmem, parcel, parentHandle, 0);
+ }
+ }
+ signalExceptionForError(env, err);
+}
+
static jstring MakeStringObjFromHidlString(JNIEnv *env, const hidl_string &s) {
String16 utf16String(s.c_str(), s.size());
@@ -877,6 +910,74 @@
return objArray;
}
+static status_t readEmbeddedHidlMemory(JNIEnv* env,
+ hardware::Parcel* parcel,
+ const hardware::hidl_memory& mem,
+ size_t parentHandle,
+ size_t parentOffset,
+ jobject* result) {
+ status_t err = hardware::readEmbeddedFromParcel(mem,
+ *parcel,
+ parentHandle,
+ parentOffset);
+ if (err == OK) {
+ // Convert to Java.
+ *result = JHidlMemory::toJava(env, mem);
+ if (*result == nullptr) {
+ err = BAD_VALUE;
+ }
+ }
+ return err;
+}
+
+static jobject JHwParcel_native_readHidlMemory(
+ JNIEnv* env, jobject thiz) {
+ hardware::Parcel* parcel =
+ JHwParcel::GetNativeContext(env, thiz)->getParcel();
+
+ jobject result = nullptr;
+
+ const hardware::hidl_memory* mem;
+ size_t parentHandle;
+
+ status_t err = parcel->readBuffer(sizeof(*mem),
+ &parentHandle,
+ reinterpret_cast<const void**>(&mem));
+ if (err == OK) {
+ err = readEmbeddedHidlMemory(env,
+ parcel,
+ *mem,
+ parentHandle,
+ 0,
+ &result);
+ }
+
+ signalExceptionForError(env, err);
+ return result;
+}
+
+static jobject JHwParcel_native_readEmbeddedHidlMemory(
+ JNIEnv* env,
+ jobject thiz,
+ jlong fieldHandle,
+ jlong parentHandle,
+ jlong offset) {
+ hardware::Parcel* parcel =
+ JHwParcel::GetNativeContext(env, thiz)->getParcel();
+
+ jobject result = nullptr;
+ const hardware::hidl_memory* mem =
+ reinterpret_cast<const hardware::hidl_memory*>(fieldHandle);
+ status_t err = readEmbeddedHidlMemory(env,
+ parcel,
+ *mem,
+ parentHandle,
+ offset,
+ &result);
+ signalExceptionForError(env, err);
+ return result;
+}
+
static jobject JHwParcel_native_readStrongBinder(JNIEnv *env, jobject thiz) {
hardware::Parcel *parcel =
JHwParcel::GetNativeContext(env, thiz)->getParcel();
@@ -1075,6 +1176,14 @@
{ "release", "()V",
(void *)JHwParcel_native_release },
+ {"writeHidlMemory", "(L" PACKAGE_PATH "/HidlMemory;)V",
+ (void*) JHwParcel_native_writeHidlMemory},
+
+ {"readHidlMemory", "()L" PACKAGE_PATH "/HidlMemory;",
+ (void*) JHwParcel_native_readHidlMemory},
+
+ {"readEmbeddedHidlMemory", "(JJJ)L" PACKAGE_PATH "/HidlMemory;",
+ (void*) JHwParcel_native_readEmbeddedHidlMemory},
};
namespace android {
diff --git a/core/jni/android_os_SystemProperties.cpp b/core/jni/android_os_SystemProperties.cpp
index 7f8bec6..7f3b32e 100644
--- a/core/jni/android_os_SystemProperties.cpp
+++ b/core/jni/android_os_SystemProperties.cpp
@@ -123,7 +123,7 @@
jboolean SystemProperties_get_boolean(JNIEnv *env, jclass, jstring keyJ,
jboolean defJ)
{
- ParseBoolResult parseResult;
+ ParseBoolResult parseResult = ParseBoolResult::kError;
ReadProperty(env, keyJ, [&](const char* value) {
parseResult = android::base::ParseBool(value);
});
@@ -168,7 +168,7 @@
jboolean SystemProperties_get_booleanH(CRITICAL_JNI_PARAMS_COMMA jlong propJ, jboolean defJ)
{
- ParseBoolResult parseResult;
+ ParseBoolResult parseResult = ParseBoolResult::kError;
auto prop = reinterpret_cast<const prop_info*>(propJ);
ReadProperty(prop, [&](const char* value) {
parseResult = android::base::ParseBool(value);
diff --git a/core/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp
index 7350396..170e467 100644
--- a/core/jni/android_view_ThreadedRenderer.cpp
+++ b/core/jni/android_view_ThreadedRenderer.cpp
@@ -180,10 +180,13 @@
if (jsurface) {
surface = android_view_Surface_getSurface(env, jsurface);
}
+ bool enableTimeout = true;
if (discardBuffer) {
+ // Currently only Surface#lockHardwareCanvas takes this path
+ enableTimeout = false;
proxy->setSwapBehavior(SwapBehavior::kSwap_discardBuffer);
}
- proxy->setSurface(surface);
+ proxy->setSurface(surface, enableTimeout);
}
static jboolean android_view_ThreadedRenderer_pause(JNIEnv* env, jobject clazz,
diff --git a/core/jni/fd_utils.cpp b/core/jni/fd_utils.cpp
index 3704ccd..8fabb23 100644
--- a/core/jni/fd_utils.cpp
+++ b/core/jni/fd_utils.cpp
@@ -34,6 +34,7 @@
// Static whitelist of open paths that the zygote is allowed to keep open.
static const char* kPathWhitelist[] = {
"/apex/com.android.conscrypt/javalib/conscrypt.jar",
+ "/apex/com.android.ipsec/javalib/ike.jar",
"/apex/com.android.media/javalib/updatable-media.jar",
"/dev/null",
"/dev/socket/zygote",
diff --git a/core/proto/android/server/activitymanagerservice.proto b/core/proto/android/server/activitymanagerservice.proto
index 8f084ab..ce2717b 100644
--- a/core/proto/android/server/activitymanagerservice.proto
+++ b/core/proto/android/server/activitymanagerservice.proto
@@ -126,11 +126,12 @@
optional .com.android.server.wm.ConfigurationContainerProto configuration_container = 1 [deprecated=true];
optional .com.android.server.wm.IdentifierProto identifier = 2;
optional string state = 3;
- optional bool visible = 4;
+ optional bool visible_requested = 4;
optional bool front_of_task = 5;
optional int32 proc_id = 6;
optional bool translucent = 7;
optional .com.android.server.wm.AppWindowTokenProto app_window_token = 8;
+ optional bool visible = 9;
}
message KeyguardControllerProto {
diff --git a/core/proto/android/server/windowmanagerservice.proto b/core/proto/android/server/windowmanagerservice.proto
index 1a4a7ce..24456d8 100644
--- a/core/proto/android/server/windowmanagerservice.proto
+++ b/core/proto/android/server/windowmanagerservice.proto
@@ -236,7 +236,7 @@
optional bool fills_parent = 7;
optional bool app_stopped = 8;
optional bool visible_requested = 9;
- optional bool client_hidden = 10;
+ optional bool client_visible = 10;
optional bool defer_hiding_client = 11;
optional bool reported_drawn = 12;
optional bool reported_visible = 13;
@@ -249,8 +249,9 @@
optional IdentifierProto starting_window = 19;
optional bool starting_displayed = 20;
optional bool starting_moved = 21;
- optional bool hidden_set_from_transferred_starting_window = 22;
+ optional bool visible_set_from_transferred_starting_window = 22;
repeated .android.graphics.RectProto frozen_bounds = 23;
+ optional bool visible = 24;
}
/* represents WindowToken */
@@ -260,7 +261,6 @@
optional WindowContainerProto window_container = 1;
optional int32 hash_code = 2;
repeated WindowStateProto windows = 3;
- optional bool hidden = 4;
optional bool waiting_to_show = 5;
optional bool paused = 6;
}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 62001aa..a6f65f9 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -499,7 +499,6 @@
<protected-broadcast android:name="android.telephony.action.CARRIER_CONFIG_CHANGED" />
<protected-broadcast android:name="android.telephony.action.DEFAULT_SUBSCRIPTION_CHANGED" />
<protected-broadcast android:name="android.telephony.action.DEFAULT_SMS_SUBSCRIPTION_CHANGED" />
- <protected-broadcast android:name="android.telephony.action.OTA_EMERGENCY_NUMBER_DB_INSTALLED" />
<protected-broadcast android:name="android.telephony.action.SECRET_CODE" />
<protected-broadcast android:name="android.telephony.action.SHOW_VOICEMAIL_NOTIFICATION" />
<protected-broadcast android:name="android.telephony.action.SUBSCRIPTION_PLANS_CHANGED" />
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 642dc92..234ffee 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -3702,8 +3702,6 @@
<flag name="flagRequestFingerprintGestures" value="0x00000200" />
<!-- Has flag {@link android.accessibilityservice.AccessibilityServiceInfo#FLAG_REQUEST_SHORTCUT_WARNING_DIALOG_SPOKEN_FEEDBACK}. -->
<flag name="flagRequestShortcutWarningDialogSpokenFeedback" value="0x00000400" />
- <!-- Has flag {@link android.accessibilityservice.AccessibilityServiceInfo#FLAG_HANDLE_SHORTCUT}. -->
- <flag name="flagHandleShortcut" value="0x00000800" />
</attr>
<!-- Component name of an activity that allows the user to modify
the settings for this service. This setting cannot be changed at runtime. -->
diff --git a/core/tests/coretests/src/android/provider/DeviceConfigTest.java b/core/tests/coretests/src/android/provider/DeviceConfigTest.java
index 0c83390..8c1c3b5 100644
--- a/core/tests/coretests/src/android/provider/DeviceConfigTest.java
+++ b/core/tests/coretests/src/android/provider/DeviceConfigTest.java
@@ -33,6 +33,9 @@
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.util.HashMap;
+import java.util.Map;
+
/** Tests that ensure appropriate settings are backed up. */
@Presubmit
@RunWith(AndroidJUnit4.class)
@@ -484,12 +487,74 @@
assertThat(properties.getString(KEY3, DEFAULT_VALUE)).isEqualTo(DEFAULT_VALUE);
}
- // TODO(mpape): resolve b/142727848 and re-enable this test
+ @Test
+ public void setProperties() {
+ Map<String, String> keyValues = new HashMap<>();
+ keyValues.put(KEY, VALUE);
+ keyValues.put(KEY2, VALUE2);
+
+ DeviceConfig.setProperties(new Properties(NAMESPACE, keyValues));
+ Properties properties = DeviceConfig.getProperties(NAMESPACE);
+ assertThat(properties.getKeyset()).containsExactly(KEY, KEY2);
+ assertThat(properties.getString(KEY, DEFAULT_VALUE)).isEqualTo(VALUE);
+ assertThat(properties.getString(KEY2, DEFAULT_VALUE)).isEqualTo(VALUE2);
+
+ Map<String, String> newKeyValues = new HashMap<>();
+ newKeyValues.put(KEY, VALUE2);
+ newKeyValues.put(KEY3, VALUE3);
+
+ DeviceConfig.setProperties(new Properties(NAMESPACE, newKeyValues));
+ properties = DeviceConfig.getProperties(NAMESPACE);
+ assertThat(properties.getKeyset()).containsExactly(KEY, KEY3);
+ assertThat(properties.getString(KEY, DEFAULT_VALUE)).isEqualTo(VALUE2);
+ assertThat(properties.getString(KEY3, DEFAULT_VALUE)).isEqualTo(VALUE3);
+
+ assertThat(properties.getKeyset()).doesNotContain(KEY2);
+ assertThat(properties.getString(KEY2, DEFAULT_VALUE)).isEqualTo(DEFAULT_VALUE);
+ }
+
+ @Test
+ public void setProperties_multipleNamespaces() {
+ Map<String, String> keyValues = new HashMap<>();
+ keyValues.put(KEY, VALUE);
+ keyValues.put(KEY2, VALUE2);
+
+ Map<String, String> keyValues2 = new HashMap<>();
+ keyValues2.put(KEY2, VALUE);
+ keyValues2.put(KEY3, VALUE2);
+
+ final String namespace2 = "namespace2";
+ DeviceConfig.setProperties(new Properties(NAMESPACE, keyValues));
+ DeviceConfig.setProperties(new Properties(namespace2, keyValues2));
+
+ Properties properties = DeviceConfig.getProperties(NAMESPACE);
+ assertThat(properties.getKeyset()).containsExactly(KEY, KEY2);
+ assertThat(properties.getString(KEY, DEFAULT_VALUE)).isEqualTo(VALUE);
+ assertThat(properties.getString(KEY2, DEFAULT_VALUE)).isEqualTo(VALUE2);
+
+ assertThat(properties.getKeyset()).doesNotContain(KEY3);
+ assertThat(properties.getString(KEY3, DEFAULT_VALUE)).isEqualTo(DEFAULT_VALUE);
+
+ properties = DeviceConfig.getProperties(namespace2);
+ assertThat(properties.getKeyset()).containsExactly(KEY2, KEY3);
+ assertThat(properties.getString(KEY2, DEFAULT_VALUE)).isEqualTo(VALUE);
+ assertThat(properties.getString(KEY3, DEFAULT_VALUE)).isEqualTo(VALUE2);
+
+ assertThat(properties.getKeyset()).doesNotContain(KEY);
+ assertThat(properties.getString(KEY, DEFAULT_VALUE)).isEqualTo(DEFAULT_VALUE);
+
+ // clean up
+ deleteViaContentProvider(namespace2, KEY);
+ deleteViaContentProvider(namespace2, KEY2);
+ deleteViaContentProvider(namespace2, KEY3);
+ }
+
+ // TODO(mpape): resolve b/142727848 and re-enable listener tests
// @Test
-// public void testOnPropertiesChangedListener() throws InterruptedException {
+// public void onPropertiesChangedListener_setPropertyCallback() throws InterruptedException {
// final CountDownLatch countDownLatch = new CountDownLatch(1);
//
-// OnPropertiesChangedListener changeListener = (properties) -> {
+// DeviceConfig.OnPropertiesChangedListener changeListener = (properties) -> {
// assertThat(properties.getNamespace()).isEqualTo(NAMESPACE);
// assertThat(properties.getKeyset()).contains(KEY);
// assertThat(properties.getString(KEY, "default_value")).isEqualTo(VALUE);
@@ -508,6 +573,42 @@
// DeviceConfig.removeOnPropertiesChangedListener(changeListener);
// }
// }
+//
+// @Test
+// public void onPropertiesChangedListener_setPropertiesCallback() throws InterruptedException {
+// final CountDownLatch countDownLatch = new CountDownLatch(1);
+// DeviceConfig.setProperty(NAMESPACE, KEY, VALUE, false);
+// DeviceConfig.setProperty(NAMESPACE, KEY2, VALUE2, false);
+//
+// Map<String, String> keyValues = new HashMap<>(2);
+// keyValues.put(KEY, VALUE2);
+// keyValues.put(KEY3, VALUE3);
+// Properties setProperties = new Properties(NAMESPACE, keyValues);
+//
+// DeviceConfig.OnPropertiesChangedListener changeListener = (properties) -> {
+// assertThat(properties.getNamespace()).isEqualTo(NAMESPACE);
+// assertThat(properties.getKeyset()).containsExactly(KEY, KEY2, KEY3);
+// // KEY updated from VALUE to VALUE2
+// assertThat(properties.getString(KEY, "default_value")).isEqualTo(VALUE2);
+// // KEY2 deleted (returns default_value)
+// assertThat(properties.getString(KEY2, "default_value")).isEqualTo("default_value");
+// //KEY3 added with VALUE3
+// assertThat(properties.getString(KEY3, "default_value")).isEqualTo(VALUE3);
+// countDownLatch.countDown();
+// };
+//
+// try {
+// DeviceConfig.addOnPropertiesChangedListener(NAMESPACE,
+// ActivityThread.currentApplication().getMainExecutor(), changeListener);
+// DeviceConfig.setProperties(setProperties);
+// assertThat(countDownLatch.await(
+// WAIT_FOR_PROPERTY_CHANGE_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)).isTrue();
+// } catch (InterruptedException e) {
+// Assert.fail(e.getMessage());
+// } finally {
+// DeviceConfig.removeOnPropertiesChangedListener(changeListener);
+// }
+// }
private static boolean deleteViaContentProvider(String namespace, String key) {
ContentResolver resolver = InstrumentationRegistry.getContext().getContentResolver();
diff --git a/core/tests/coretests/src/android/util/StatsEventTest.java b/core/tests/coretests/src/android/util/StatsEventTest.java
new file mode 100644
index 0000000..93f11db
--- /dev/null
+++ b/core/tests/coretests/src/android/util/StatsEventTest.java
@@ -0,0 +1,466 @@
+/*
+ * 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.util;
+
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+
+import android.os.SystemClock;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.google.common.collect.Range;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+/**
+ * Internal tests for {@link StatsEvent}.
+ */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class StatsEventTest {
+
+ @Test
+ public void testNoFields() {
+ final long minTimestamp = SystemClock.elapsedRealtimeNanos();
+ final StatsEvent statsEvent = StatsEvent.newBuilder().build();
+ final long maxTimestamp = SystemClock.elapsedRealtimeNanos();
+
+ final int expectedAtomId = 0;
+ assertThat(statsEvent.getAtomId()).isEqualTo(expectedAtomId);
+
+ final ByteBuffer buffer =
+ ByteBuffer.wrap(statsEvent.getBytes()).order(ByteOrder.LITTLE_ENDIAN);
+
+ assertWithMessage("Root element in buffer is not TYPE_ERRORS")
+ .that(buffer.get()).isEqualTo(StatsEvent.TYPE_ERRORS);
+
+ assertWithMessage("Incorrect number of elements in root object")
+ .that(buffer.get()).isEqualTo(3);
+
+ assertWithMessage("First element is not timestamp")
+ .that(buffer.get()).isEqualTo(StatsEvent.TYPE_LONG);
+
+ assertWithMessage("Incorrect timestamp")
+ .that(buffer.getLong()).isIn(Range.closed(minTimestamp, maxTimestamp));
+
+ assertWithMessage("Second element is not atom id")
+ .that(buffer.get()).isEqualTo(StatsEvent.TYPE_INT);
+
+ assertWithMessage("Incorrect atom id")
+ .that(buffer.getInt()).isEqualTo(expectedAtomId);
+
+ final int errorMask = buffer.getInt();
+
+ assertWithMessage("ERROR_NO_ATOM_ID should be the only error in the error mask")
+ .that(errorMask).isEqualTo(StatsEvent.ERROR_NO_ATOM_ID);
+
+ assertThat(statsEvent.getNumBytes()).isEqualTo(buffer.position());
+
+ statsEvent.release();
+ }
+
+ @Test
+ public void testIntBooleanIntInt() {
+ final int expectedAtomId = 109;
+ final int field1 = 1;
+ final boolean field2 = true;
+ final int field3 = 3;
+ final int field4 = 4;
+
+ final long minTimestamp = SystemClock.elapsedRealtimeNanos();
+ final StatsEvent statsEvent = StatsEvent.newBuilder()
+ .setAtomId(expectedAtomId)
+ .writeInt(field1)
+ .writeBoolean(field2)
+ .writeInt(field3)
+ .writeInt(field4)
+ .build();
+ final long maxTimestamp = SystemClock.elapsedRealtimeNanos();
+
+ assertThat(statsEvent.getAtomId()).isEqualTo(expectedAtomId);
+
+ final ByteBuffer buffer =
+ ByteBuffer.wrap(statsEvent.getBytes()).order(ByteOrder.LITTLE_ENDIAN);
+
+ assertWithMessage("Root element in buffer is not TYPE_OBJECT")
+ .that(buffer.get()).isEqualTo(StatsEvent.TYPE_OBJECT);
+
+ assertWithMessage("Incorrect number of elements in root object")
+ .that(buffer.get()).isEqualTo(6);
+
+ assertWithMessage("First element is not timestamp")
+ .that(buffer.get()).isEqualTo(StatsEvent.TYPE_LONG);
+
+ assertWithMessage("Incorrect timestamp")
+ .that(buffer.getLong()).isIn(Range.closed(minTimestamp, maxTimestamp));
+
+ assertWithMessage("Second element is not atom id")
+ .that(buffer.get()).isEqualTo(StatsEvent.TYPE_INT);
+
+ assertWithMessage("Incorrect atom id")
+ .that(buffer.getInt()).isEqualTo(expectedAtomId);
+
+ assertWithMessage("First field is not Int")
+ .that(buffer.get()).isEqualTo(StatsEvent.TYPE_INT);
+
+ assertWithMessage("Incorrect field 1")
+ .that(buffer.getInt()).isEqualTo(field1);
+
+ assertWithMessage("Second field is not Boolean")
+ .that(buffer.get()).isEqualTo(StatsEvent.TYPE_BOOLEAN);
+
+ assertWithMessage("Incorrect field 2")
+ .that(buffer.get()).isEqualTo(1);
+
+ assertWithMessage("Third field is not Int")
+ .that(buffer.get()).isEqualTo(StatsEvent.TYPE_INT);
+
+ assertWithMessage("Incorrect field 3")
+ .that(buffer.getInt()).isEqualTo(field3);
+
+ assertWithMessage("Fourth field is not Int")
+ .that(buffer.get()).isEqualTo(StatsEvent.TYPE_INT);
+
+ assertWithMessage("Incorrect field 4")
+ .that(buffer.getInt()).isEqualTo(field4);
+
+ assertThat(statsEvent.getNumBytes()).isEqualTo(buffer.position());
+
+ statsEvent.release();
+ }
+
+ @Test
+ public void testStringFloatByteArray() {
+ final int expectedAtomId = 109;
+ final String field1 = "Str 1";
+ final float field2 = 9.334f;
+ final byte[] field3 = new byte[] { 56, 23, 89, -120 };
+
+ final long minTimestamp = SystemClock.elapsedRealtimeNanos();
+ final StatsEvent statsEvent = StatsEvent.newBuilder()
+ .setAtomId(expectedAtomId)
+ .writeString(field1)
+ .writeFloat(field2)
+ .writeByteArray(field3)
+ .build();
+ final long maxTimestamp = SystemClock.elapsedRealtimeNanos();
+
+ assertThat(statsEvent.getAtomId()).isEqualTo(expectedAtomId);
+
+ final ByteBuffer buffer =
+ ByteBuffer.wrap(statsEvent.getBytes()).order(ByteOrder.LITTLE_ENDIAN);
+
+ assertWithMessage("Root element in buffer is not TYPE_OBJECT")
+ .that(buffer.get()).isEqualTo(StatsEvent.TYPE_OBJECT);
+
+ assertWithMessage("Incorrect number of elements in root object")
+ .that(buffer.get()).isEqualTo(5);
+
+ assertWithMessage("First element is not timestamp")
+ .that(buffer.get()).isEqualTo(StatsEvent.TYPE_LONG);
+
+ assertWithMessage("Incorrect timestamp")
+ .that(buffer.getLong()).isIn(Range.closed(minTimestamp, maxTimestamp));
+
+ assertWithMessage("Second element is not atom id")
+ .that(buffer.get()).isEqualTo(StatsEvent.TYPE_INT);
+
+ assertWithMessage("Incorrect atom id")
+ .that(buffer.getInt()).isEqualTo(expectedAtomId);
+
+ assertWithMessage("First field is not String")
+ .that(buffer.get()).isEqualTo(StatsEvent.TYPE_STRING);
+
+ final String field1Actual = getStringFromByteBuffer(buffer);
+ assertWithMessage("Incorrect field 1")
+ .that(field1Actual).isEqualTo(field1);
+
+ assertWithMessage("Second field is not Float")
+ .that(buffer.get()).isEqualTo(StatsEvent.TYPE_FLOAT);
+
+ assertWithMessage("Incorrect field 2")
+ .that(buffer.getFloat()).isEqualTo(field2);
+
+ assertWithMessage("Third field is not byte array")
+ .that(buffer.get()).isEqualTo(StatsEvent.TYPE_BYTE_ARRAY);
+
+ final byte[] field3Actual = getByteArrayFromByteBuffer(buffer);
+ assertWithMessage("Incorrect field 3")
+ .that(field3Actual).isEqualTo(field3);
+
+ assertThat(statsEvent.getNumBytes()).isEqualTo(buffer.position());
+
+ statsEvent.release();
+ }
+
+ @Test
+ public void testAttributionChainLong() {
+ final int expectedAtomId = 109;
+ final int[] uids = new int[] { 1, 2, 3, 4, 5 };
+ final String[] tags = new String[] { "1", "2", "3", "4", "5" };
+ final long field2 = -230909823L;
+
+ final long minTimestamp = SystemClock.elapsedRealtimeNanos();
+ final StatsEvent statsEvent = StatsEvent.newBuilder()
+ .setAtomId(expectedAtomId)
+ .writeAttributionChain(uids, tags)
+ .writeLong(field2)
+ .build();
+ final long maxTimestamp = SystemClock.elapsedRealtimeNanos();
+
+ assertThat(statsEvent.getAtomId()).isEqualTo(expectedAtomId);
+
+ final ByteBuffer buffer =
+ ByteBuffer.wrap(statsEvent.getBytes()).order(ByteOrder.LITTLE_ENDIAN);
+
+ assertWithMessage("Root element in buffer is not TYPE_OBJECT")
+ .that(buffer.get()).isEqualTo(StatsEvent.TYPE_OBJECT);
+
+ assertWithMessage("Incorrect number of elements in root object")
+ .that(buffer.get()).isEqualTo(4);
+
+ assertWithMessage("First element is not timestamp")
+ .that(buffer.get()).isEqualTo(StatsEvent.TYPE_LONG);
+
+ assertWithMessage("Incorrect timestamp")
+ .that(buffer.getLong()).isIn(Range.closed(minTimestamp, maxTimestamp));
+
+ assertWithMessage("Second element is not atom id")
+ .that(buffer.get()).isEqualTo(StatsEvent.TYPE_INT);
+
+ assertWithMessage("Incorrect atom id")
+ .that(buffer.getInt()).isEqualTo(expectedAtomId);
+
+ assertWithMessage("First field is not Attribution Chain")
+ .that(buffer.get()).isEqualTo(StatsEvent.TYPE_ATTRIBUTION_CHAIN);
+
+ assertWithMessage("Incorrect number of attribution nodes")
+ .that(buffer.get()).isEqualTo((byte) uids.length);
+
+ for (int i = 0; i < tags.length; i++) {
+ assertWithMessage("Incorrect uid in Attribution Chain")
+ .that(buffer.getInt()).isEqualTo(uids[i]);
+
+ final String tag = getStringFromByteBuffer(buffer);
+ assertWithMessage("Incorrect tag in Attribution Chain")
+ .that(tag).isEqualTo(tags[i]);
+ }
+
+ assertWithMessage("Second field is not Long")
+ .that(buffer.get()).isEqualTo(StatsEvent.TYPE_LONG);
+
+ assertWithMessage("Incorrect field 2")
+ .that(buffer.getLong()).isEqualTo(field2);
+
+ assertThat(statsEvent.getNumBytes()).isEqualTo(buffer.position());
+
+ statsEvent.release();
+ }
+
+ @Test
+ public void testKeyValuePairs() {
+ final int expectedAtomId = 109;
+ final SparseIntArray intMap = new SparseIntArray();
+ final SparseLongArray longMap = new SparseLongArray();
+ final SparseArray<String> stringMap = new SparseArray<>();
+ final SparseArray<Float> floatMap = new SparseArray<>();
+ intMap.put(1, -1);
+ intMap.put(2, -2);
+ stringMap.put(3, "abc");
+ stringMap.put(4, "2h");
+ floatMap.put(9, -234.344f);
+
+ final long minTimestamp = SystemClock.elapsedRealtimeNanos();
+ final StatsEvent statsEvent = StatsEvent.newBuilder()
+ .setAtomId(expectedAtomId)
+ .writeKeyValuePairs(intMap, longMap, stringMap, floatMap)
+ .build();
+ final long maxTimestamp = SystemClock.elapsedRealtimeNanos();
+
+ assertThat(statsEvent.getAtomId()).isEqualTo(expectedAtomId);
+
+ final ByteBuffer buffer =
+ ByteBuffer.wrap(statsEvent.getBytes()).order(ByteOrder.LITTLE_ENDIAN);
+
+ assertWithMessage("Root element in buffer is not TYPE_OBJECT")
+ .that(buffer.get()).isEqualTo(StatsEvent.TYPE_OBJECT);
+
+ assertWithMessage("Incorrect number of elements in root object")
+ .that(buffer.get()).isEqualTo(3);
+
+ assertWithMessage("First element is not timestamp")
+ .that(buffer.get()).isEqualTo(StatsEvent.TYPE_LONG);
+
+ assertWithMessage("Incorrect timestamp")
+ .that(buffer.getLong()).isIn(Range.closed(minTimestamp, maxTimestamp));
+
+ assertWithMessage("Second element is not atom id")
+ .that(buffer.get()).isEqualTo(StatsEvent.TYPE_INT);
+
+ assertWithMessage("Incorrect atom id")
+ .that(buffer.getInt()).isEqualTo(expectedAtomId);
+
+ assertWithMessage("First field is not KeyValuePairs")
+ .that(buffer.get()).isEqualTo(StatsEvent.TYPE_KEY_VALUE_PAIRS);
+
+ assertWithMessage("Incorrect number of key value pairs")
+ .that(buffer.get()).isEqualTo(
+ (byte) (intMap.size() + longMap.size() + stringMap.size()
+ + floatMap.size()));
+
+ for (int i = 0; i < intMap.size(); i++) {
+ assertWithMessage("Incorrect key in intMap")
+ .that(buffer.getInt()).isEqualTo(intMap.keyAt(i));
+ assertWithMessage("The type id of the value should be TYPE_INT in intMap")
+ .that(buffer.get()).isEqualTo(StatsEvent.TYPE_INT);
+ assertWithMessage("Incorrect value in intMap")
+ .that(buffer.getInt()).isEqualTo(intMap.valueAt(i));
+ }
+
+ for (int i = 0; i < longMap.size(); i++) {
+ assertWithMessage("Incorrect key in longMap")
+ .that(buffer.getInt()).isEqualTo(longMap.keyAt(i));
+ assertWithMessage("The type id of the value should be TYPE_LONG in longMap")
+ .that(buffer.get()).isEqualTo(StatsEvent.TYPE_LONG);
+ assertWithMessage("Incorrect value in longMap")
+ .that(buffer.getLong()).isEqualTo(longMap.valueAt(i));
+ }
+
+ for (int i = 0; i < stringMap.size(); i++) {
+ assertWithMessage("Incorrect key in stringMap")
+ .that(buffer.getInt()).isEqualTo(stringMap.keyAt(i));
+ assertWithMessage("The type id of the value should be TYPE_STRING in stringMap")
+ .that(buffer.get()).isEqualTo(StatsEvent.TYPE_STRING);
+ final String value = getStringFromByteBuffer(buffer);
+ assertWithMessage("Incorrect value in stringMap")
+ .that(value).isEqualTo(stringMap.valueAt(i));
+ }
+
+ for (int i = 0; i < floatMap.size(); i++) {
+ assertWithMessage("Incorrect key in floatMap")
+ .that(buffer.getInt()).isEqualTo(floatMap.keyAt(i));
+ assertWithMessage("The type id of the value should be TYPE_FLOAT in floatMap")
+ .that(buffer.get()).isEqualTo(StatsEvent.TYPE_FLOAT);
+ assertWithMessage("Incorrect value in floatMap")
+ .that(buffer.getFloat()).isEqualTo(floatMap.valueAt(i));
+ }
+
+ assertThat(statsEvent.getNumBytes()).isEqualTo(buffer.position());
+
+ statsEvent.release();
+ }
+
+ @Test
+ public void testSingleAnnotations() {
+ final int expectedAtomId = 109;
+ final int field1 = 1;
+ final byte field1AnnotationId = 45;
+ final boolean field1AnnotationValue = false;
+ final boolean field2 = true;
+ final byte field2AnnotationId = 1;
+ final int field2AnnotationValue = 23;
+
+ final long minTimestamp = SystemClock.elapsedRealtimeNanos();
+ final StatsEvent statsEvent = StatsEvent.newBuilder()
+ .setAtomId(expectedAtomId)
+ .writeInt(field1)
+ .addBooleanAnnotation(field1AnnotationId, field1AnnotationValue)
+ .writeBoolean(field2)
+ .addIntAnnotation(field2AnnotationId, field2AnnotationValue)
+ .build();
+ final long maxTimestamp = SystemClock.elapsedRealtimeNanos();
+
+ assertThat(statsEvent.getAtomId()).isEqualTo(expectedAtomId);
+
+ final ByteBuffer buffer =
+ ByteBuffer.wrap(statsEvent.getBytes()).order(ByteOrder.LITTLE_ENDIAN);
+
+ assertWithMessage("Root element in buffer is not TYPE_OBJECT")
+ .that(buffer.get()).isEqualTo(StatsEvent.TYPE_OBJECT);
+
+ assertWithMessage("Incorrect number of elements in root object")
+ .that(buffer.get()).isEqualTo(4);
+
+ assertWithMessage("First element is not timestamp")
+ .that(buffer.get()).isEqualTo(StatsEvent.TYPE_LONG);
+
+ assertWithMessage("Incorrect timestamp")
+ .that(buffer.getLong()).isIn(Range.closed(minTimestamp, maxTimestamp));
+
+ assertWithMessage("Second element is not atom id")
+ .that(buffer.get()).isEqualTo(StatsEvent.TYPE_INT);
+
+ assertWithMessage("Incorrect atom id")
+ .that(buffer.getInt()).isEqualTo(expectedAtomId);
+
+ final byte field1Header = buffer.get();
+ final int field1AnnotationValueCount = field1Header >> 4;
+ final byte field1Type = (byte) (field1Header & 0x0F);
+ assertWithMessage("First field is not Int")
+ .that(field1Type).isEqualTo(StatsEvent.TYPE_INT);
+ assertWithMessage("First field annotation count is wrong")
+ .that(field1AnnotationValueCount).isEqualTo(1);
+ assertWithMessage("Incorrect field 1")
+ .that(buffer.getInt()).isEqualTo(field1);
+ assertWithMessage("First field's annotation id is wrong")
+ .that(buffer.get()).isEqualTo(field1AnnotationId);
+ assertWithMessage("First field's annotation type is wrong")
+ .that(buffer.get()).isEqualTo(StatsEvent.TYPE_BOOLEAN);
+ assertWithMessage("First field's annotation value is wrong")
+ .that(buffer.get()).isEqualTo(field1AnnotationValue ? 1 : 0);
+
+ final byte field2Header = buffer.get();
+ final int field2AnnotationValueCount = field2Header >> 4;
+ final byte field2Type = (byte) (field2Header & 0x0F);
+ assertWithMessage("Second field is not boolean")
+ .that(field2Type).isEqualTo(StatsEvent.TYPE_BOOLEAN);
+ assertWithMessage("Second field annotation count is wrong")
+ .that(field2AnnotationValueCount).isEqualTo(1);
+ assertWithMessage("Incorrect field 2")
+ .that(buffer.get()).isEqualTo(field2 ? 1 : 0);
+ assertWithMessage("Second field's annotation id is wrong")
+ .that(buffer.get()).isEqualTo(field2AnnotationId);
+ assertWithMessage("Second field's annotation type is wrong")
+ .that(buffer.get()).isEqualTo(StatsEvent.TYPE_INT);
+ assertWithMessage("Second field's annotation value is wrong")
+ .that(buffer.getInt()).isEqualTo(field2AnnotationValue);
+
+ assertThat(statsEvent.getNumBytes()).isEqualTo(buffer.position());
+
+ statsEvent.release();
+ }
+
+ private static byte[] getByteArrayFromByteBuffer(final ByteBuffer buffer) {
+ final int numBytes = buffer.getInt();
+ byte[] bytes = new byte[numBytes];
+ buffer.get(bytes);
+ return bytes;
+ }
+
+ private static String getStringFromByteBuffer(final ByteBuffer buffer) {
+ final byte[] bytes = getByteArrayFromByteBuffer(buffer);
+ return new String(bytes, UTF_8);
+ }
+}
diff --git a/core/tests/coretests/src/com/android/internal/app/ResolverActivityTest.java b/core/tests/coretests/src/com/android/internal/app/ResolverActivityTest.java
index a401e21..344c286 100644
--- a/core/tests/coretests/src/com/android/internal/app/ResolverActivityTest.java
+++ b/core/tests/coretests/src/com/android/internal/app/ResolverActivityTest.java
@@ -50,6 +50,7 @@
import com.android.internal.widget.ResolverDrawerLayout;
import org.junit.Before;
+import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -103,6 +104,7 @@
assertThat(chosen[0], is(toChoose));
}
+ @Ignore // Failing - b/144929805
@Test
public void setMaxHeight() throws Exception {
Intent sendIntent = createSendImageIntent();
@@ -146,6 +148,7 @@
resolverList.getHeight() == initialResolverHeight);
}
+ @Ignore // Failing - b/144929805
@Test
public void setShowAtTopToTrue() throws Exception {
Intent sendIntent = createSendImageIntent();
diff --git a/data/etc/services.core.protolog.json b/data/etc/services.core.protolog.json
index 5c48d91..440b885 100644
--- a/data/etc/services.core.protolog.json
+++ b/data/etc/services.core.protolog.json
@@ -55,6 +55,12 @@
"group": "WM_DEBUG_REMOTE_ANIMATIONS",
"at": "com\/android\/server\/wm\/RemoteAnimationController.java"
},
+ "-2006946193": {
+ "message": "setClientVisible: %s clientVisible=%b Callers=%s",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_APP_TRANSITIONS",
+ "at": "com\/android\/server\/wm\/ActivityRecord.java"
+ },
"-2002500255": {
"message": "Defer removing snapshot surface in %dms",
"level": "VERBOSE",
@@ -73,10 +79,10 @@
"group": "WM_ERROR",
"at": "com\/android\/server\/wm\/WindowManagerService.java"
},
- "-1972506791": {
- "message": "Set freezing of %s: hidden=%b freezing=%b visibleRequested=%b. %s",
- "level": "INFO",
- "group": "WM_DEBUG_ORIENTATION",
+ "-1976550065": {
+ "message": "commitVisibility: %s: visible=%b visibleRequested=%b",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_APP_TRANSITIONS",
"at": "com\/android\/server\/wm\/ActivityRecord.java"
},
"-1963461591": {
@@ -85,12 +91,6 @@
"group": "WM_DEBUG_ADD_REMOVE",
"at": "com\/android\/server\/wm\/WindowManagerService.java"
},
- "-1958209312": {
- "message": "Clear freezing of %s: hidden=%b freezing=%b",
- "level": "VERBOSE",
- "group": "WM_DEBUG_ORIENTATION",
- "at": "com\/android\/server\/wm\/ActivityRecord.java"
- },
"-1953668890": {
"message": "Can't start recents animation, nextAppTransition=%s",
"level": "DEBUG",
@@ -307,12 +307,6 @@
"group": "WM_DEBUG_ADD_REMOVE",
"at": "com\/android\/server\/wm\/ActivityRecord.java"
},
- "-1456549051": {
- "message": "setClientHidden: %s clientHidden=%b Callers=%s",
- "level": "VERBOSE",
- "group": "WM_DEBUG_APP_TRANSITIONS",
- "at": "com\/android\/server\/wm\/ActivityRecord.java"
- },
"-1455600136": {
"message": "Attempted to add Dream window with unknown token %s. Aborting.",
"level": "WARN",
@@ -547,12 +541,6 @@
"group": "WM_DEBUG_STARTING_WINDOW",
"at": "com\/android\/server\/wm\/WindowState.java"
},
- "-931184679": {
- "message": "Changing app %s hidden=%b performLayout=%b",
- "level": "VERBOSE",
- "group": "WM_DEBUG_APP_TRANSITIONS",
- "at": "com\/android\/server\/wm\/ActivityRecord.java"
- },
"-928291778": {
"message": "applyAnimation: anim=%s nextAppTransition=%d transit=%s Callers=%s",
"level": "VERBOSE",
@@ -841,6 +829,12 @@
"group": "WM_DEBUG_APP_TRANSITIONS",
"at": "com\/android\/server\/wm\/AppTransitionController.java"
},
+ "-374767836": {
+ "message": "setAppVisibility(%s, visible=%b): %s visible=%b mVisibleRequested=%b Callers=%s",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_APP_TRANSITIONS",
+ "at": "com\/android\/server\/wm\/ActivityRecord.java"
+ },
"-371630969": {
"message": "New wallpaper target=%s, oldWallpaper=%s, openingApps=%s, closingApps=%s",
"level": "VERBOSE",
@@ -883,12 +877,6 @@
"group": "WM_DEBUG_ORIENTATION",
"at": "com\/android\/server\/wm\/ActivityRecord.java"
},
- "-229838822": {
- "message": "setAppVisibility(%s, visible=%b): %s hidden=%b mVisibleRequested=%b Callers=%s",
- "level": "VERBOSE",
- "group": "WM_DEBUG_APP_TRANSITIONS",
- "at": "com\/android\/server\/wm\/ActivityRecord.java"
- },
"-198463978": {
"message": "updateRotationUnchecked: alwaysSendConfiguration=%b forceRelayout=%b",
"level": "VERBOSE",
@@ -1273,6 +1261,12 @@
"group": "WM_DEBUG_SCREEN_ON",
"at": "com\/android\/server\/wm\/WindowManagerService.java"
},
+ "466506262": {
+ "message": "Clear freezing of %s: visible=%b freezing=%b",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_ORIENTATION",
+ "at": "com\/android\/server\/wm\/ActivityRecord.java"
+ },
"474000473": {
"message": "No stack above target stack=%s",
"level": "DEBUG",
@@ -1483,6 +1477,12 @@
"group": "WM_DEBUG_REMOTE_ANIMATIONS",
"at": "com\/android\/server\/wm\/RemoteAnimationController.java"
},
+ "841702299": {
+ "message": "Changing app %s visible=%b performLayout=%b",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_APP_TRANSITIONS",
+ "at": "com\/android\/server\/wm\/ActivityRecord.java"
+ },
"845234215": {
"message": "App is requesting an orientation, return %d for display id=%d",
"level": "VERBOSE",
@@ -1891,6 +1891,12 @@
"group": "WM_DEBUG_STARTING_WINDOW",
"at": "com\/android\/server\/wm\/ActivityRecord.java"
},
+ "1746778201": {
+ "message": "Set freezing of %s: visible=%b freezing=%b visibleRequested=%b. %s",
+ "level": "INFO",
+ "group": "WM_DEBUG_ORIENTATION",
+ "at": "com\/android\/server\/wm\/ActivityRecord.java"
+ },
"1747941491": {
"message": "SURFACE controller=%s alpha=%f matrix=[%f*%f,%f*%f][%f*%f,%f*%f]: %s",
"level": "INFO",
@@ -1987,12 +1993,6 @@
"group": "WM_DEBUG_REMOTE_ANIMATIONS",
"at": "com\/android\/server\/wm\/RemoteAnimationController.java"
},
- "1965198071": {
- "message": "commitVisibility: %s: hidden=%b visibleRequested=%b",
- "level": "VERBOSE",
- "group": "WM_DEBUG_APP_TRANSITIONS",
- "at": "com\/android\/server\/wm\/ActivityRecord.java"
- },
"1984470582": {
"message": "Creating TaskScreenshotAnimatable: task: %s width: %d height: %d",
"level": "DEBUG",
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index f086768..8490221 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -140,13 +140,15 @@
mAnimationContext->destroy();
}
-void CanvasContext::setSurface(sp<Surface>&& surface) {
+void CanvasContext::setSurface(sp<Surface>&& surface, bool enableTimeout) {
ATRACE_CALL();
if (surface) {
mNativeSurface = new ReliableSurface{std::move(surface)};
- // TODO: Fix error handling & re-shorten timeout
- ANativeWindow_setDequeueTimeout(mNativeSurface.get(), 4000_ms);
+ if (enableTimeout) {
+ // TODO: Fix error handling & re-shorten timeout
+ ANativeWindow_setDequeueTimeout(mNativeSurface.get(), 4000_ms);
+ }
} else {
mNativeSurface = nullptr;
}
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index b192d46..4490f80 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -111,7 +111,7 @@
// Won't take effect until next EGLSurface creation
void setSwapBehavior(SwapBehavior swapBehavior);
- void setSurface(sp<Surface>&& surface);
+ void setSurface(sp<Surface>&& surface, bool enableTimeout = true);
bool pauseSurface();
void setStopped(bool stopped);
bool hasSurface() const { return mNativeSurface.get(); }
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index 4f7ad7b..f9e401a 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -78,9 +78,10 @@
mRenderThread.queue().runSync([this, name]() { mContext->setName(std::string(name)); });
}
-void RenderProxy::setSurface(const sp<Surface>& surface) {
- mRenderThread.queue().post(
- [this, surf = surface]() mutable { mContext->setSurface(std::move(surf)); });
+void RenderProxy::setSurface(const sp<Surface>& surface, bool enableTimeout) {
+ mRenderThread.queue().post([this, surf = surface, enableTimeout]() mutable {
+ mContext->setSurface(std::move(surf), enableTimeout);
+ });
}
void RenderProxy::allocateBuffers() {
diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h
index e6fe1d4..4683e1d 100644
--- a/libs/hwui/renderthread/RenderProxy.h
+++ b/libs/hwui/renderthread/RenderProxy.h
@@ -69,7 +69,7 @@
ANDROID_API bool loadSystemProperties();
ANDROID_API void setName(const char* name);
- ANDROID_API void setSurface(const sp<Surface>& surface);
+ ANDROID_API void setSurface(const sp<Surface>& surface, bool enableTimeout = true);
ANDROID_API void allocateBuffers();
ANDROID_API bool pause();
ANDROID_API void setStopped(bool stopped);
diff --git a/libs/input/tests/PointerController_test.cpp b/libs/input/tests/PointerController_test.cpp
index 92efb4e..b36406d 100644
--- a/libs/input/tests/PointerController_test.cpp
+++ b/libs/input/tests/PointerController_test.cpp
@@ -32,8 +32,8 @@
CURSOR_TYPE_HOVER,
CURSOR_TYPE_TOUCH,
CURSOR_TYPE_ANCHOR,
- CURSOR_TYPE_ADDITIONAL_1,
- CURSOR_TYPE_ADDITIONAL_2,
+ CURSOR_TYPE_ADDITIONAL,
+ CURSOR_TYPE_ADDITIONAL_ANIM,
CURSOR_TYPE_CUSTOM = -1,
};
@@ -79,13 +79,18 @@
SpriteIcon icon;
PointerAnimation anim;
- for (int32_t cursorType : {CURSOR_TYPE_ADDITIONAL_1, CURSOR_TYPE_ADDITIONAL_2}) {
- loadPointerIconForType(&icon, cursorType);
- anim.animationFrames.push_back(icon);
- anim.durationPerFrame = 10;
- (*outResources)[cursorType] = icon;
- (*outAnimationResources)[cursorType] = anim;
- }
+ // CURSOR_TYPE_ADDITIONAL doesn't have animation resource.
+ int32_t cursorType = CURSOR_TYPE_ADDITIONAL;
+ loadPointerIconForType(&icon, cursorType);
+ (*outResources)[cursorType] = icon;
+
+ // CURSOR_TYPE_ADDITIONAL_ANIM has animation resource.
+ cursorType = CURSOR_TYPE_ADDITIONAL_ANIM;
+ loadPointerIconForType(&icon, cursorType);
+ anim.animationFrames.push_back(icon);
+ anim.durationPerFrame = 10;
+ (*outResources)[cursorType] = icon;
+ (*outAnimationResources)[cursorType] = anim;
}
int32_t MockPointerControllerPolicyInterface::getDefaultPointerIconId() {
@@ -178,7 +183,7 @@
TEST_F(PointerControllerTest, updatePointerIcon) {
mPointerController->unfade(PointerController::TRANSITION_IMMEDIATE);
- int32_t type = CURSOR_TYPE_ADDITIONAL_1;
+ int32_t type = CURSOR_TYPE_ADDITIONAL;
std::pair<float, float> hotspot = getHotSpotCoordinatesForType(type);
EXPECT_CALL(*mPointerSprite, setVisible(true));
EXPECT_CALL(*mPointerSprite, setAlpha(1.0f));
diff --git a/location/java/android/location/Location.java b/location/java/android/location/Location.java
index 27274d1..db48ee7 100644
--- a/location/java/android/location/Location.java
+++ b/location/java/android/location/Location.java
@@ -161,7 +161,10 @@
* <p>By default time, latitude and longitude are 0, and the location
* has no bearing, altitude, speed, accuracy or extras.
*
- * @param provider the name of the provider that generated this location
+ * @param provider the source that provides the location. It can be of type
+ * {@link LocationManager#GPS_PROVIDER}, {@link LocationManager#NETWORK_PROVIDER},
+ * or {@link LocationManager#PASSIVE_PROVIDER}. You can also define your own
+ * provider string, in which case an empty string is a valid provider.
*/
public Location(String provider) {
mProvider = provider;
diff --git a/location/java/android/location/OnNmeaMessageListener.java b/location/java/android/location/OnNmeaMessageListener.java
index ccf6ce8..05647bc 100644
--- a/location/java/android/location/OnNmeaMessageListener.java
+++ b/location/java/android/location/OnNmeaMessageListener.java
@@ -28,7 +28,9 @@
/**
* Called when an NMEA message is received.
* @param message NMEA message
- * @param timestamp milliseconds since January 1, 1970.
+ * @param timestamp Date and time of the location fix, as reported by the GNSS
+ * chipset. The value is specified in milliseconds since 0:00
+ * UTC 1 January 1970.
*/
void onNmeaMessage(String message, long timestamp);
}
diff --git a/location/java/com/android/internal/location/gnssmetrics/GnssMetrics.java b/location/java/com/android/internal/location/gnssmetrics/GnssMetrics.java
index e0bff74..c20dc61 100644
--- a/location/java/com/android/internal/location/gnssmetrics/GnssMetrics.java
+++ b/location/java/com/android/internal/location/gnssmetrics/GnssMetrics.java
@@ -114,6 +114,7 @@
* Logs the status of a location report received from the HAL
*/
public void logReceivedLocationStatus(boolean isSuccessful) {
+ StatsLog.write(StatsLog.GPS_LOCATION_STATUS_REPORTED, isSuccessful);
if (!isSuccessful) {
mLocationFailureStatistics.addItem(1.0);
return;
@@ -130,6 +131,7 @@
DEFAULT_TIME_BETWEEN_FIXES_MILLISECS, desiredTimeBetweenFixesMilliSeconds)) - 1;
if (numReportMissed > 0) {
for (int i = 0; i < numReportMissed; i++) {
+ StatsLog.write(StatsLog.GPS_LOCATION_STATUS_REPORTED, false);
mLocationFailureStatistics.addItem(1.0);
}
}
@@ -140,6 +142,7 @@
*/
public void logTimeToFirstFixMilliSecs(int timeToFirstFixMilliSeconds) {
mTimeToFirstFixSecStatistics.addItem((double) (timeToFirstFixMilliSeconds / 1000));
+ StatsLog.write(StatsLog.GPS_TIME_TO_FIRST_FIX_REPORTED, timeToFirstFixMilliSeconds);
}
/**
diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java
index a3a8777..d64e4ef 100644
--- a/media/java/android/media/AudioSystem.java
+++ b/media/java/android/media/AudioSystem.java
@@ -30,7 +30,9 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
+import java.util.HashSet;
import java.util.Map;
+import java.util.Set;
/* IF YOU CHANGE ANY OF THE CONSTANTS IN THIS FILE, DO NOT FORGET
* TO UPDATE THE CORRESPONDING NATIVE GLUE AND AudioManager.java.
@@ -543,51 +545,75 @@
public static final int DEVICE_OUT_DEFAULT = DEVICE_BIT_DEFAULT;
- public static final int DEVICE_OUT_ALL = (DEVICE_OUT_EARPIECE |
- DEVICE_OUT_SPEAKER |
- DEVICE_OUT_WIRED_HEADSET |
- DEVICE_OUT_WIRED_HEADPHONE |
- DEVICE_OUT_BLUETOOTH_SCO |
- DEVICE_OUT_BLUETOOTH_SCO_HEADSET |
- DEVICE_OUT_BLUETOOTH_SCO_CARKIT |
- DEVICE_OUT_BLUETOOTH_A2DP |
- DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES |
- DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER |
- DEVICE_OUT_HDMI |
- DEVICE_OUT_ANLG_DOCK_HEADSET |
- DEVICE_OUT_DGTL_DOCK_HEADSET |
- DEVICE_OUT_USB_ACCESSORY |
- DEVICE_OUT_USB_DEVICE |
- DEVICE_OUT_REMOTE_SUBMIX |
- DEVICE_OUT_TELEPHONY_TX |
- DEVICE_OUT_LINE |
- DEVICE_OUT_HDMI_ARC |
- DEVICE_OUT_SPDIF |
- DEVICE_OUT_FM |
- DEVICE_OUT_AUX_LINE |
- DEVICE_OUT_SPEAKER_SAFE |
- DEVICE_OUT_IP |
- DEVICE_OUT_BUS |
- DEVICE_OUT_PROXY |
- DEVICE_OUT_USB_HEADSET |
- DEVICE_OUT_HEARING_AID |
- DEVICE_OUT_DEFAULT);
- public static final int DEVICE_OUT_ALL_A2DP = (DEVICE_OUT_BLUETOOTH_A2DP |
- DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES |
- DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER);
- public static final int DEVICE_OUT_ALL_SCO = (DEVICE_OUT_BLUETOOTH_SCO |
- DEVICE_OUT_BLUETOOTH_SCO_HEADSET |
- DEVICE_OUT_BLUETOOTH_SCO_CARKIT);
+ // Deprecated in R because multiple device types are no longer accessed as a bit mask.
+ // Removing this will get lint warning about changing hidden apis.
@UnsupportedAppUsage
public static final int DEVICE_OUT_ALL_USB = (DEVICE_OUT_USB_ACCESSORY |
DEVICE_OUT_USB_DEVICE |
DEVICE_OUT_USB_HEADSET);
- public static final int DEVICE_OUT_ALL_HDMI_SYSTEM_AUDIO = (DEVICE_OUT_AUX_LINE |
- DEVICE_OUT_HDMI_ARC |
- DEVICE_OUT_SPDIF);
- public static final int DEVICE_ALL_HDMI_SYSTEM_AUDIO_AND_SPEAKER =
- (DEVICE_OUT_ALL_HDMI_SYSTEM_AUDIO |
- DEVICE_OUT_SPEAKER);
+
+ public static final Set<Integer> DEVICE_OUT_ALL_SET;
+ public static final Set<Integer> DEVICE_OUT_ALL_A2DP_SET;
+ public static final Set<Integer> DEVICE_OUT_ALL_SCO_SET;
+ public static final Set<Integer> DEVICE_OUT_ALL_USB_SET;
+ public static final Set<Integer> DEVICE_OUT_ALL_HDMI_SYSTEM_AUDIO_SET;
+ public static final Set<Integer> DEVICE_ALL_HDMI_SYSTEM_AUDIO_AND_SPEAKER_SET;
+ static {
+ DEVICE_OUT_ALL_SET = new HashSet<>();
+ DEVICE_OUT_ALL_SET.add(DEVICE_OUT_EARPIECE);
+ DEVICE_OUT_ALL_SET.add(DEVICE_OUT_SPEAKER);
+ DEVICE_OUT_ALL_SET.add(DEVICE_OUT_WIRED_HEADSET);
+ DEVICE_OUT_ALL_SET.add(DEVICE_OUT_WIRED_HEADPHONE);
+ DEVICE_OUT_ALL_SET.add(DEVICE_OUT_BLUETOOTH_SCO);
+ DEVICE_OUT_ALL_SET.add(DEVICE_OUT_BLUETOOTH_SCO_HEADSET);
+ DEVICE_OUT_ALL_SET.add(DEVICE_OUT_BLUETOOTH_SCO_CARKIT);
+ DEVICE_OUT_ALL_SET.add(DEVICE_OUT_BLUETOOTH_A2DP);
+ DEVICE_OUT_ALL_SET.add(DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES);
+ DEVICE_OUT_ALL_SET.add(DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER);
+ DEVICE_OUT_ALL_SET.add(DEVICE_OUT_HDMI);
+ DEVICE_OUT_ALL_SET.add(DEVICE_OUT_ANLG_DOCK_HEADSET);
+ DEVICE_OUT_ALL_SET.add(DEVICE_OUT_DGTL_DOCK_HEADSET);
+ DEVICE_OUT_ALL_SET.add(DEVICE_OUT_USB_ACCESSORY);
+ DEVICE_OUT_ALL_SET.add(DEVICE_OUT_USB_DEVICE);
+ DEVICE_OUT_ALL_SET.add(DEVICE_OUT_REMOTE_SUBMIX);
+ DEVICE_OUT_ALL_SET.add(DEVICE_OUT_TELEPHONY_TX);
+ DEVICE_OUT_ALL_SET.add(DEVICE_OUT_LINE);
+ DEVICE_OUT_ALL_SET.add(DEVICE_OUT_HDMI_ARC);
+ DEVICE_OUT_ALL_SET.add(DEVICE_OUT_SPDIF);
+ DEVICE_OUT_ALL_SET.add(DEVICE_OUT_FM);
+ DEVICE_OUT_ALL_SET.add(DEVICE_OUT_AUX_LINE);
+ DEVICE_OUT_ALL_SET.add(DEVICE_OUT_SPEAKER_SAFE);
+ DEVICE_OUT_ALL_SET.add(DEVICE_OUT_IP);
+ DEVICE_OUT_ALL_SET.add(DEVICE_OUT_BUS);
+ DEVICE_OUT_ALL_SET.add(DEVICE_OUT_PROXY);
+ DEVICE_OUT_ALL_SET.add(DEVICE_OUT_USB_HEADSET);
+ DEVICE_OUT_ALL_SET.add(DEVICE_OUT_HEARING_AID);
+ DEVICE_OUT_ALL_SET.add(DEVICE_OUT_DEFAULT);
+
+ DEVICE_OUT_ALL_A2DP_SET = new HashSet<>();
+ DEVICE_OUT_ALL_A2DP_SET.add(DEVICE_OUT_BLUETOOTH_A2DP);
+ DEVICE_OUT_ALL_A2DP_SET.add(DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES);
+ DEVICE_OUT_ALL_A2DP_SET.add(DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER);
+
+ DEVICE_OUT_ALL_SCO_SET = new HashSet<>();
+ DEVICE_OUT_ALL_SCO_SET.add(DEVICE_OUT_BLUETOOTH_SCO);
+ DEVICE_OUT_ALL_SCO_SET.add(DEVICE_OUT_BLUETOOTH_SCO_HEADSET);
+ DEVICE_OUT_ALL_SCO_SET.add(DEVICE_OUT_BLUETOOTH_SCO_CARKIT);
+
+ DEVICE_OUT_ALL_USB_SET = new HashSet<>();
+ DEVICE_OUT_ALL_USB_SET.add(DEVICE_OUT_USB_ACCESSORY);
+ DEVICE_OUT_ALL_USB_SET.add(DEVICE_OUT_USB_DEVICE);
+ DEVICE_OUT_ALL_USB_SET.add(DEVICE_OUT_USB_HEADSET);
+
+ DEVICE_OUT_ALL_HDMI_SYSTEM_AUDIO_SET = new HashSet<>();
+ DEVICE_OUT_ALL_HDMI_SYSTEM_AUDIO_SET.add(DEVICE_OUT_AUX_LINE);
+ DEVICE_OUT_ALL_HDMI_SYSTEM_AUDIO_SET.add(DEVICE_OUT_HDMI_ARC);
+ DEVICE_OUT_ALL_HDMI_SYSTEM_AUDIO_SET.add(DEVICE_OUT_SPDIF);
+
+ DEVICE_ALL_HDMI_SYSTEM_AUDIO_AND_SPEAKER_SET = new HashSet<>();
+ DEVICE_ALL_HDMI_SYSTEM_AUDIO_AND_SPEAKER_SET.addAll(DEVICE_OUT_ALL_HDMI_SYSTEM_AUDIO_SET);
+ DEVICE_ALL_HDMI_SYSTEM_AUDIO_AND_SPEAKER_SET.add(DEVICE_OUT_SPEAKER);
+ }
// input devices
@UnsupportedAppUsage
@@ -635,37 +661,47 @@
@UnsupportedAppUsage
public static final int DEVICE_IN_DEFAULT = DEVICE_BIT_IN | DEVICE_BIT_DEFAULT;
- public static final int DEVICE_IN_ALL = (DEVICE_IN_COMMUNICATION |
- DEVICE_IN_AMBIENT |
- DEVICE_IN_BUILTIN_MIC |
- DEVICE_IN_BLUETOOTH_SCO_HEADSET |
- DEVICE_IN_WIRED_HEADSET |
- DEVICE_IN_HDMI |
- DEVICE_IN_TELEPHONY_RX |
- DEVICE_IN_BACK_MIC |
- DEVICE_IN_REMOTE_SUBMIX |
- DEVICE_IN_ANLG_DOCK_HEADSET |
- DEVICE_IN_DGTL_DOCK_HEADSET |
- DEVICE_IN_USB_ACCESSORY |
- DEVICE_IN_USB_DEVICE |
- DEVICE_IN_FM_TUNER |
- DEVICE_IN_TV_TUNER |
- DEVICE_IN_LINE |
- DEVICE_IN_SPDIF |
- DEVICE_IN_BLUETOOTH_A2DP |
- DEVICE_IN_LOOPBACK |
- DEVICE_IN_IP |
- DEVICE_IN_BUS |
- DEVICE_IN_PROXY |
- DEVICE_IN_USB_HEADSET |
- DEVICE_IN_BLUETOOTH_BLE |
- DEVICE_IN_HDMI_ARC |
- DEVICE_IN_ECHO_REFERENCE |
- DEVICE_IN_DEFAULT);
- public static final int DEVICE_IN_ALL_SCO = DEVICE_IN_BLUETOOTH_SCO_HEADSET;
- public static final int DEVICE_IN_ALL_USB = (DEVICE_IN_USB_ACCESSORY |
- DEVICE_IN_USB_DEVICE |
- DEVICE_IN_USB_HEADSET);
+ public static final Set<Integer> DEVICE_IN_ALL_SET;
+ public static final Set<Integer> DEVICE_IN_ALL_SCO_SET;
+ public static final Set<Integer> DEVICE_IN_ALL_USB_SET;
+ static {
+ DEVICE_IN_ALL_SET = new HashSet<>();
+ DEVICE_IN_ALL_SET.add(DEVICE_IN_COMMUNICATION);
+ DEVICE_IN_ALL_SET.add(DEVICE_IN_AMBIENT);
+ DEVICE_IN_ALL_SET.add(DEVICE_IN_BUILTIN_MIC);
+ DEVICE_IN_ALL_SET.add(DEVICE_IN_BLUETOOTH_SCO_HEADSET);
+ DEVICE_IN_ALL_SET.add(DEVICE_IN_WIRED_HEADSET);
+ DEVICE_IN_ALL_SET.add(DEVICE_IN_HDMI);
+ DEVICE_IN_ALL_SET.add(DEVICE_IN_TELEPHONY_RX);
+ DEVICE_IN_ALL_SET.add(DEVICE_IN_BACK_MIC);
+ DEVICE_IN_ALL_SET.add(DEVICE_IN_REMOTE_SUBMIX);
+ DEVICE_IN_ALL_SET.add(DEVICE_IN_ANLG_DOCK_HEADSET);
+ DEVICE_IN_ALL_SET.add(DEVICE_IN_DGTL_DOCK_HEADSET);
+ DEVICE_IN_ALL_SET.add(DEVICE_IN_USB_ACCESSORY);
+ DEVICE_IN_ALL_SET.add(DEVICE_IN_USB_DEVICE);
+ DEVICE_IN_ALL_SET.add(DEVICE_IN_FM_TUNER);
+ DEVICE_IN_ALL_SET.add(DEVICE_IN_TV_TUNER);
+ DEVICE_IN_ALL_SET.add(DEVICE_IN_LINE);
+ DEVICE_IN_ALL_SET.add(DEVICE_IN_SPDIF);
+ DEVICE_IN_ALL_SET.add(DEVICE_IN_BLUETOOTH_A2DP);
+ DEVICE_IN_ALL_SET.add(DEVICE_IN_LOOPBACK);
+ DEVICE_IN_ALL_SET.add(DEVICE_IN_IP);
+ DEVICE_IN_ALL_SET.add(DEVICE_IN_BUS);
+ DEVICE_IN_ALL_SET.add(DEVICE_IN_PROXY);
+ DEVICE_IN_ALL_SET.add(DEVICE_IN_USB_HEADSET);
+ DEVICE_IN_ALL_SET.add(DEVICE_IN_BLUETOOTH_BLE);
+ DEVICE_IN_ALL_SET.add(DEVICE_IN_HDMI_ARC);
+ DEVICE_IN_ALL_SET.add(DEVICE_IN_ECHO_REFERENCE);
+ DEVICE_IN_ALL_SET.add(DEVICE_IN_DEFAULT);
+
+ DEVICE_IN_ALL_SCO_SET = new HashSet<>();
+ DEVICE_IN_ALL_SCO_SET.add(DEVICE_IN_BLUETOOTH_SCO_HEADSET);
+
+ DEVICE_IN_ALL_USB_SET = new HashSet<>();
+ DEVICE_IN_ALL_USB_SET.add(DEVICE_IN_USB_ACCESSORY);
+ DEVICE_IN_ALL_USB_SET.add(DEVICE_IN_USB_DEVICE);
+ DEVICE_IN_ALL_USB_SET.add(DEVICE_IN_USB_HEADSET);
+ }
// device states, must match AudioSystem::device_connection_state
@UnsupportedAppUsage
@@ -1229,6 +1265,40 @@
return getPlatformType(context) == PLATFORM_TELEVISION || forceSingleVolume;
}
+ /**
+ * Return a set of audio device types from a bit mask audio device type, which may
+ * represent multiple audio device types.
+ * FIXME: Remove this when getting ride of bit mask usage of audio device types.
+ */
+ public static Set<Integer> generateAudioDeviceTypesSet(int types) {
+ Set<Integer> deviceTypes = new HashSet<>();
+ Set<Integer> allDeviceTypes =
+ (types & DEVICE_BIT_IN) == 0 ? DEVICE_OUT_ALL_SET : DEVICE_IN_ALL_SET;
+ for (int deviceType : allDeviceTypes) {
+ if ((types & deviceType) == deviceType) {
+ deviceTypes.add(deviceType);
+ }
+ }
+ return deviceTypes;
+ }
+
+ /**
+ * Return the intersection of two audio device types collections.
+ */
+ public static Set<Integer> intersectionAudioDeviceTypes(
+ @NonNull Set<Integer> a, @NonNull Set<Integer> b) {
+ Set<Integer> intersection = new HashSet<>(a);
+ intersection.retainAll(b);
+ return intersection;
+ }
+
+ /**
+ * Return true if the audio device types collection only contains the given device type.
+ */
+ public static boolean isSingleAudioDeviceType(@NonNull Set<Integer> types, int type) {
+ return types.size() == 1 && types.contains(type);
+ }
+
public static final int DEFAULT_MUTE_STREAMS_AFFECTED =
(1 << STREAM_MUSIC) |
(1 << STREAM_RING) |
diff --git a/media/java/android/media/IMediaRouterService.aidl b/media/java/android/media/IMediaRouterService.aidl
index ced8615..81a7ee2 100644
--- a/media/java/android/media/IMediaRouterService.aidl
+++ b/media/java/android/media/IMediaRouterService.aidl
@@ -43,6 +43,7 @@
void setControlCategories(IMediaRouterClient client, in List<String> categories);
// Methods for media router 2
+ List<MediaRoute2Info> getSystemRoutes();
void registerClient2(IMediaRouter2Client client, String packageName);
void unregisterClient2(IMediaRouter2Client client);
void sendControlRequest(IMediaRouter2Client client, in MediaRoute2Info route, in Intent request);
diff --git a/media/java/android/media/MediaRouter2.java b/media/java/android/media/MediaRouter2.java
index 74d26f0..94ac77a 100644
--- a/media/java/android/media/MediaRouter2.java
+++ b/media/java/android/media/MediaRouter2.java
@@ -131,6 +131,25 @@
mPackageName = mContext.getPackageName();
//TODO: read control categories from the manifest
mHandler = new Handler(Looper.getMainLooper());
+
+ List<MediaRoute2Info> currentSystemRoutes = null;
+ try {
+ currentSystemRoutes = mMediaRouterService.getSystemRoutes();
+ } catch (RemoteException ex) {
+ Log.e(TAG, "Unable to get current currentSystemRoutes", ex);
+ }
+
+ if (currentSystemRoutes == null || currentSystemRoutes.isEmpty()) {
+ throw new RuntimeException("Null or empty currentSystemRoutes. Something is wrong.");
+ }
+
+ for (MediaRoute2Info route : currentSystemRoutes) {
+ mRoutes.put(route.getId(), route);
+ }
+ // The first route is the currently selected system route.
+ // For example, if there are two system routes (BT and device speaker),
+ // BT will be the first route in the list.
+ mSelectedRoute = currentSystemRoutes.get(0);
}
/**
@@ -409,6 +428,10 @@
}
void addRoutesOnHandler(List<MediaRoute2Info> routes) {
+ // TODO: When onRoutesAdded is first called,
+ // 1) clear mRoutes before adding the routes
+ // 2) Call onRouteSelected(system_route, reason_fallback) if previously selected route
+ // does not exist anymore. => We may need 'boolean MediaRoute2Info#isSystemRoute()'.
List<MediaRoute2Info> addedRoutes = new ArrayList<>();
for (MediaRoute2Info route : routes) {
mRoutes.put(route.getUniqueId(), route);
diff --git a/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouter2Test.java b/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouter2Test.java
new file mode 100644
index 0000000..2c60d6b
--- /dev/null
+++ b/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouter2Test.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.mediaroutertest;
+
+import static org.junit.Assert.assertNotNull;
+
+import android.content.Context;
+import android.media.MediaRoute2Info;
+import android.media.MediaRouter2;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class MediaRouter2Test {
+ Context mContext;
+
+ @Before
+ public void setUp() throws Exception {
+ mContext = InstrumentationRegistry.getTargetContext();
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ }
+
+ @Test
+ public void testGetSelectedRoute_afterCreation() throws Exception {
+ MediaRouter2 router = MediaRouter2.getInstance(mContext);
+ MediaRoute2Info initiallySelectedRoute = router.getSelectedRoute();
+ assertNotNull(initiallySelectedRoute);
+ }
+}
diff --git a/native/graphics/jni/bitmap.cpp b/native/graphics/jni/bitmap.cpp
index ff14832..1aebeaf 100644
--- a/native/graphics/jni/bitmap.cpp
+++ b/native/graphics/jni/bitmap.cpp
@@ -15,7 +15,7 @@
*/
#include <android/bitmap.h>
-#include <android/graphics/Bitmap.h>
+#include <android/graphics/bitmap.h>
int AndroidBitmap_getInfo(JNIEnv* env, jobject jbitmap,
AndroidBitmapInfo* info) {
@@ -24,7 +24,7 @@
}
if (info) {
- android::bitmap::imageInfo(env, jbitmap, info);
+ *info = ABitmap_getInfoFromJava(env, jbitmap);
}
return ANDROID_BITMAP_RESULT_SUCCESS;
}
@@ -34,11 +34,15 @@
return ANDROID_BITMAP_RESULT_BAD_PARAMETER;
}
- void* addr = android::bitmap::lockPixels(env, jbitmap);
+ android::graphics::Bitmap bitmap(env, jbitmap);
+ void* addr = bitmap.isValid() ? bitmap.getPixels() : nullptr;
+
if (!addr) {
return ANDROID_BITMAP_RESULT_JNI_EXCEPTION;
}
+ ABitmap_acquireRef(bitmap.get());
+
if (addrPtr) {
*addrPtr = addr;
}
@@ -50,9 +54,13 @@
return ANDROID_BITMAP_RESULT_BAD_PARAMETER;
}
- bool unlocked = android::bitmap::unlockPixels(env, jbitmap);
- if (!unlocked) {
+ android::graphics::Bitmap bitmap(env, jbitmap);
+
+ if (!bitmap.isValid()) {
return ANDROID_BITMAP_RESULT_JNI_EXCEPTION;
}
+
+ bitmap.notifyPixelsChanged();
+ ABitmap_releaseRef(bitmap.get());
return ANDROID_BITMAP_RESULT_SUCCESS;
}
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java
index b188dc3..4543019 100644
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java
@@ -50,9 +50,6 @@
@Singleton
public class FullscreenUserSwitcher {
private static final String TAG = FullscreenUserSwitcher.class.getSimpleName();
- // Because user 0 is headless, user count for single user is 2
- private static final int NUMBER_OF_BACKGROUND_USERS = 1;
-
private final Context mContext;
private final Resources mResources;
private final UserManager mUserManager;
@@ -137,27 +134,18 @@
/* isStartGuestSession= */ false,
/* isAddUser= */ false,
/* isForeground= */ true);
- // For single user without trusted device, hide the user switcher.
- if (!hasMultipleUsers() && !hasTrustedDevice(initialUser)) {
- dismissUserSwitcher();
- return;
- }
- // Show unlock dialog for initial user
+
+ // If the initial user has trusted device, display the unlock dialog on the keyguard.
if (hasTrustedDevice(initialUser)) {
mUnlockDialogHelper.showUnlockDialogAfterDelay(initialUser,
mOnHideListener);
+ } else {
+ // If no trusted device, dismiss the keyguard.
+ dismissUserSwitcher();
}
}
/**
- * Check if there is only one possible user to login in.
- * In a Multi-User system there is always one background user (user 0)
- */
- private boolean hasMultipleUsers() {
- return mUserManager.getUserCount() > NUMBER_OF_BACKGROUND_USERS + 1;
- }
-
- /**
* Makes user grid visible.
*/
public void show() {
diff --git a/packages/CarrierDefaultApp/tests/unit/src/com/android/carrierdefaultapp/CarrierDefaultReceiverTest.java b/packages/CarrierDefaultApp/tests/unit/src/com/android/carrierdefaultapp/CarrierDefaultReceiverTest.java
index 5d84d64..1928ad9 100644
--- a/packages/CarrierDefaultApp/tests/unit/src/com/android/carrierdefaultapp/CarrierDefaultReceiverTest.java
+++ b/packages/CarrierDefaultApp/tests/unit/src/com/android/carrierdefaultapp/CarrierDefaultReceiverTest.java
@@ -21,7 +21,6 @@
import android.content.Intent;
import android.os.PersistableBundle;
import android.telephony.CarrierConfigManager;
-import android.telephony.Rlog;
import android.telephony.TelephonyManager;
import android.test.InstrumentationTestCase;
@@ -90,12 +89,10 @@
Intent intent = new Intent(TelephonyIntents.ACTION_CARRIER_SIGNAL_REDIRECTED);
intent.putExtra(PhoneConstants.SUBSCRIPTION_KEY, subId);
- Rlog.d(TAG, "OnReceive redirection intent");
mReceiver.onReceive(mContext, intent);
mContext.waitForMs(100);
- Rlog.d(TAG, "verify carrier action: showPortalNotification");
verify(mNotificationMgr, times(1)).notify(mString.capture(), mInt.capture(),
mNotification.capture());
assertEquals(PORTAL_NOTIFICATION_ID, (int) mInt.getValue());
@@ -103,7 +100,6 @@
PendingIntent pendingIntent = mNotification.getValue().contentIntent;
assertNotNull(pendingIntent);
- Rlog.d(TAG, "verify carrier action: disable all metered apns");
verify(mTelephonyMgr).setCarrierDataEnabled(eq(false));
}
}
diff --git a/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/ActivityTile.java b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/ActivityTile.java
index 8cd33a5..b739ee6 100644
--- a/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/ActivityTile.java
+++ b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/ActivityTile.java
@@ -18,6 +18,7 @@
import android.content.Context;
import android.content.Intent;
+import android.content.pm.ActivityInfo;
import android.content.pm.ComponentInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
@@ -33,7 +34,7 @@
public class ActivityTile extends Tile {
private static final String TAG = "ActivityTile";
- public ActivityTile(ComponentInfo info, String category) {
+ public ActivityTile(ActivityInfo info, String category) {
super(info, category);
setMetaData(info.metaData);
}
diff --git a/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/MasterSwitchController.java b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/MasterSwitchController.java
new file mode 100644
index 0000000..a12aa83
--- /dev/null
+++ b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/MasterSwitchController.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.drawer;
+
+import android.os.Bundle;
+
+/**
+ * A controller that manages event for master switch.
+ */
+public abstract class MasterSwitchController extends SwitchController {
+
+ @Override
+ protected final MetaData getMetaData() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ final Bundle getBundle() {
+ throw new UnsupportedOperationException();
+ }
+}
diff --git a/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/ProviderTile.java b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/ProviderTile.java
index b2ba5de..312d30e 100644
--- a/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/ProviderTile.java
+++ b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/ProviderTile.java
@@ -42,10 +42,10 @@
private String mAuthority;
private String mKey;
- public ProviderTile(ComponentInfo info, String category, Bundle metaData) {
+ public ProviderTile(ProviderInfo info, String category, Bundle metaData) {
super(info, category);
setMetaData(metaData);
- mAuthority = ((ProviderInfo) info).authority;
+ mAuthority = info.authority;
mKey = metaData.getString(META_DATA_PREFERENCE_KEYHINT);
}
diff --git a/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/SwitchController.java b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/SwitchController.java
index e48da86..23669b2 100644
--- a/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/SwitchController.java
+++ b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/SwitchController.java
@@ -108,7 +108,7 @@
Bundle getBundle() {
final MetaData metaData = getMetaData();
if (metaData == null) {
- throw new IllegalArgumentException("Should not return null in getMetaData()");
+ throw new NullPointerException("Should not return null in getMetaData()");
}
final Bundle bundle = metaData.build();
diff --git a/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/SwitchesProvider.java b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/SwitchesProvider.java
index a05c7d5..73f1a90 100644
--- a/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/SwitchesProvider.java
+++ b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/SwitchesProvider.java
@@ -55,7 +55,7 @@
private String mAuthority;
private final Map<String, SwitchController> mControllerMap = new LinkedHashMap<>();
- private final List<Bundle> mSwitchList = new ArrayList<>();
+ private final List<Bundle> mSwitchDataList = new ArrayList<>();
/**
* Get a list of {@link SwitchController} for this provider.
@@ -88,7 +88,9 @@
controller.setAuthority(mAuthority);
mControllerMap.put(key, controller);
- mSwitchList.add(controller.getBundle());
+ if (!(controller instanceof MasterSwitchController)) {
+ mSwitchDataList.add(controller.getBundle());
+ }
});
return true;
}
@@ -101,7 +103,7 @@
: null;
if (TextUtils.isEmpty(key)) {
if (METHOD_GET_SWITCH_DATA.equals(method)) {
- bundle.putParcelableList(EXTRA_SWITCH_DATA, mSwitchList);
+ bundle.putParcelableList(EXTRA_SWITCH_DATA, mSwitchDataList);
return bundle;
}
return null;
@@ -114,7 +116,10 @@
switch (method) {
case METHOD_GET_SWITCH_DATA:
- return controller.getBundle();
+ if (!(controller instanceof MasterSwitchController)) {
+ return controller.getBundle();
+ }
+ break;
case METHOD_GET_PROVIDER_ICON:
if (controller instanceof ProviderIcon) {
return ((ProviderIcon) controller).getProviderIcon();
diff --git a/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/TileUtils.java b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/TileUtils.java
index 71ffff7..f93faeb 100644
--- a/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/TileUtils.java
+++ b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/TileUtils.java
@@ -244,15 +244,15 @@
// TODO: Needs much optimization, too many PM queries going on here.
if (user.getIdentifier() == ActivityManager.getCurrentUser()) {
// Only add Settings for this user.
- getTilesForAction(context, user, SETTINGS_ACTION, cache, null, tiles, true);
- getTilesForAction(context, user, OPERATOR_SETTINGS, cache,
+ loadTilesForAction(context, user, SETTINGS_ACTION, cache, null, tiles, true);
+ loadTilesForAction(context, user, OPERATOR_SETTINGS, cache,
OPERATOR_DEFAULT_CATEGORY, tiles, false);
- getTilesForAction(context, user, MANUFACTURER_SETTINGS, cache,
+ loadTilesForAction(context, user, MANUFACTURER_SETTINGS, cache,
MANUFACTURER_DEFAULT_CATEGORY, tiles, false);
}
if (setup) {
- getTilesForAction(context, user, EXTRA_SETTINGS_ACTION, cache, null, tiles, false);
- getTilesForAction(context, user, IA_SETTINGS_ACTION, cache, null, tiles, false);
+ loadTilesForAction(context, user, EXTRA_SETTINGS_ACTION, cache, null, tiles, false);
+ loadTilesForAction(context, user, IA_SETTINGS_ACTION, cache, null, tiles, false);
}
}
@@ -284,18 +284,18 @@
}
@VisibleForTesting
- static void getTilesForAction(Context context,
+ static void loadTilesForAction(Context context,
UserHandle user, String action, Map<Pair<String, String>, Tile> addedCache,
String defaultCategory, List<Tile> outTiles, boolean requireSettings) {
final Intent intent = new Intent(action);
if (requireSettings) {
intent.setPackage(SETTING_PKG);
}
- getActivityTiles(context, user, addedCache, defaultCategory, outTiles, intent);
- getProviderTiles(context, user, addedCache, defaultCategory, outTiles, intent);
+ loadActivityTiles(context, user, addedCache, defaultCategory, outTiles, intent);
+ loadProviderTiles(context, user, addedCache, defaultCategory, outTiles, intent);
}
- private static void getActivityTiles(Context context,
+ private static void loadActivityTiles(Context context,
UserHandle user, Map<Pair<String, String>, Tile> addedCache,
String defaultCategory, List<Tile> outTiles, Intent intent) {
final PackageManager pm = context.getPackageManager();
@@ -308,11 +308,11 @@
}
final ActivityInfo activityInfo = resolved.activityInfo;
final Bundle metaData = activityInfo.metaData;
- getTile(user, addedCache, defaultCategory, outTiles, intent, metaData, activityInfo);
+ loadTile(user, addedCache, defaultCategory, outTiles, intent, metaData, activityInfo);
}
}
- private static void getProviderTiles(Context context,
+ private static void loadProviderTiles(Context context,
UserHandle user, Map<Pair<String, String>, Tile> addedCache,
String defaultCategory, List<Tile> outTiles, Intent intent) {
final PackageManager pm = context.getPackageManager();
@@ -330,13 +330,13 @@
continue;
}
for (Bundle metaData : switchData) {
- getTile(user, addedCache, defaultCategory, outTiles, intent, metaData,
+ loadTile(user, addedCache, defaultCategory, outTiles, intent, metaData,
providerInfo);
}
}
}
- private static void getTile(UserHandle user, Map<Pair<String, String>, Tile> addedCache,
+ private static void loadTile(UserHandle user, Map<Pair<String, String>, Tile> addedCache,
String defaultCategory, List<Tile> outTiles, Intent intent, Bundle metaData,
ComponentInfo componentInfo) {
String categoryKey = defaultCategory;
@@ -359,8 +359,8 @@
Tile tile = addedCache.get(key);
if (tile == null) {
tile = isProvider
- ? new ProviderTile(componentInfo, categoryKey, metaData)
- : new ActivityTile(componentInfo, categoryKey);
+ ? new ProviderTile((ProviderInfo) componentInfo, categoryKey, metaData)
+ : new ActivityTile((ActivityInfo) componentInfo, categoryKey);
addedCache.put(key, tile);
} else {
tile.setMetaData(metaData);
@@ -516,7 +516,7 @@
* @param value Boolean associated with the key
* @return Bundle associated with the action, if returned by the content provider
*/
- public static Bundle putBooleanToUri(Context context, Uri uri,
+ public static Bundle putBooleanToUriAndGetResult(Context context, Uri uri,
Map<String, IContentProvider> providerMap, String key, boolean value) {
final Bundle bundle = new Bundle();
bundle.putBoolean(key, value);
diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml
index 3ff5cf4..6289b87 100644
--- a/packages/SettingsLib/res/values-af/strings.xml
+++ b/packages/SettingsLib/res/values-af/strings.xml
@@ -233,6 +233,7 @@
<string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Gebruik Bluetooth-oudiokodek\nKeuse"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Bluetooth-oudiovoorbeeldkoers"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Gebruik Bluetooth-oudiokodek\nKeuse: monsterkoers"</string>
+ <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Dofgemaak beteken dit word nie deur foon of kopstuk gesteun nie"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Bluetooth-oudiobisse per voorbeeld"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Gebruik Bluetooth-oudiokodek\nKeuse: bisse per monster"</string>
<string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Bluetooth-oudiokanaalmodus"</string>
diff --git a/packages/SettingsLib/res/values-am/strings.xml b/packages/SettingsLib/res/values-am/strings.xml
index 264d8de..45545a7 100644
--- a/packages/SettingsLib/res/values-am/strings.xml
+++ b/packages/SettingsLib/res/values-am/strings.xml
@@ -233,6 +233,7 @@
<string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"የብሉቱዝ ኦዲዮ ኮዴክ አስጀምር\nምርጫ"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"የብሉቱዝ ኦዲዮ ናሙና ፍጥነት"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"የብሉቱዝ ኦዲዮ ኮዴክን አስጀምር\nምርጫ፦ የናሙና ደረጃ አሰጣጥ"</string>
+ <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"ግራጫ መልክ ሲታይ በስልክ ወይም በጆሮ ማዳመጫ አይደገፍም ማለት ነው"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"የብሉቱዝ ኦዲዮ ቢት በናሙና"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"የብሉቱዝ ኦዲዮ ኮዴክን አስጀምር\nምርጫ፦ ቢትስ በናሙና"</string>
<string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"የብሉቱዝ ኦዲዮ ሰርጥ ሁነታ"</string>
diff --git a/packages/SettingsLib/res/values-ar/strings.xml b/packages/SettingsLib/res/values-ar/strings.xml
index c230236..af06fc7 100644
--- a/packages/SettingsLib/res/values-ar/strings.xml
+++ b/packages/SettingsLib/res/values-ar/strings.xml
@@ -233,6 +233,7 @@
<string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"اختيار برنامج ترميز الصوت لمشغّل\nالبلوتوث"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"معدّل عيّنة صوت بلوتوث"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"اختيار برنامج ترميز الصوت لمشغّل\nالبلوتوث: معدّل العيّنة"</string>
+ <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"\"غير متوفّر\" تعني أن الهاتف أو سماعة الرأس لا يدعمان برنامج الترميز"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"وحدات البت لكل عيّنة في صوت بلوتوث"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"اختيار برنامج ترميز الصوت لمشغّل\nالبلوتوث: عدد وحدات البت لكل عيّنة"</string>
<string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"وضع قناة صوت بلوتوث"</string>
diff --git a/packages/SettingsLib/res/values-as/strings.xml b/packages/SettingsLib/res/values-as/strings.xml
index ab0ed29..49eabe1 100644
--- a/packages/SettingsLib/res/values-as/strings.xml
+++ b/packages/SettingsLib/res/values-as/strings.xml
@@ -233,6 +233,7 @@
<string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"ব্লুটুথ অডিঅ\' ক\'ডেকৰ বাছনি\nআৰম্ভ কৰক"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"ব্লুটুথ অডিঅ\' ছেম্পল ৰেইট"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"ব্লুটুথ অডিঅ\' LDAC বাছনি\nআৰম্ভ কৰক: নমুনাৰ হাৰ"</string>
+ <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"ধোঁৱাবৰণীয়া হৈ থকা মানে এয়া ফ’ন অথবা হেডছেটটোৱে সমৰ্থন নকৰে"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"প্ৰতি ছেম্পলত ব্লুটুথ অডিঅ\' বিটসমূহ"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"ব্লুটুথ অডিঅ\' ক\'ডেকৰ বাছনি\nআৰম্ভ কৰক: প্ৰতি নমুনা ইমান বিট"</string>
<string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"ব্লুটুথ অডিঅ\' চ্চেনেল ম\'ড"</string>
diff --git a/packages/SettingsLib/res/values-az/strings.xml b/packages/SettingsLib/res/values-az/strings.xml
index fe62d31..158f13a 100644
--- a/packages/SettingsLib/res/values-az/strings.xml
+++ b/packages/SettingsLib/res/values-az/strings.xml
@@ -233,6 +233,7 @@
<string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Bluetooth Audio KodeK\nSeçimini aktiv edin"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Bluetooth Audio Nümunə Göstəricisi"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Bluetooth Audio Kodek\nSeçimini aktiv edin: Nümunə Göstəricisi"</string>
+ <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Boz rəng telefon və ya qulaqlıq tərəfindən dəstəklənmədiyini bildirir"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Hər Nümunə Üçün Bluetooth Audio Bit"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Bluetooth Audio Kodek\nSeçimini aktiv edin: Hər Nümunə üçün Bit"</string>
<string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Bluetooth Audio Kanal Rejimi"</string>
diff --git a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
index 1619584..2709df5 100644
--- a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
+++ b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
@@ -233,6 +233,7 @@
<string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Izaberite Bluetooth audio kodek\n"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Brzina uzorkovanja za Bluetooth audio"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Izaberite Bluetooth audio kodek:\n brzina uzorkovanja"</string>
+ <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Ako je neka stavka zasivljena, to znači da je telefon ili slušalice ne podržavaju"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Bitova po uzorku za Bluetooth audio"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Izaberite Bluetooth audio kodek:\n broj bitova po uzorku"</string>
<string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Režim kanala za Bluetooth audio"</string>
diff --git a/packages/SettingsLib/res/values-be/strings.xml b/packages/SettingsLib/res/values-be/strings.xml
index 0f2df49..40295ea 100644
--- a/packages/SettingsLib/res/values-be/strings.xml
+++ b/packages/SettingsLib/res/values-be/strings.xml
@@ -233,6 +233,7 @@
<string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Уключыць кодэк Bluetooth Audio\nВыбар"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Частата дыскрэтызацыі Bluetooth Audio"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Уключыць кодэк Bluetooth Audio\nВыбар: частата дыскрэтызацыі"</string>
+ <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Шэрым афарбаваны функцыі, якія не падтрымліваюцца тэлефонам або гарнітурай"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Біты на сэмпл для Bluetooth Audio"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Уключыць кодэк Bluetooth Audio\nВыбар: біты на дыскрэтызацыю"</string>
<string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Канальны рэжым Bluetooth Audio"</string>
diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml
index a3be2812..7b25374 100644
--- a/packages/SettingsLib/res/values-bg/strings.xml
+++ b/packages/SettingsLib/res/values-bg/strings.xml
@@ -233,6 +233,7 @@
<string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Задействане на аудиокодек за Bluetooth\nИзбор"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Честота на дискретизация за звука през Bluetooth"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Задействане на аудиокодек за Bluetooth\nИзбор: Честота на дискретизация"</string>
+ <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Неактивното състояние означава, че елементът не се поддържа от телефона или слушалките"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Битове на дискрет за звука през Bluetooth"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Задействане на аудиокодек за Bluetooth\nИзбор: Битове на дискрет"</string>
<string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Режим на канала на звука през Bluetooth"</string>
diff --git a/packages/SettingsLib/res/values-bn/strings.xml b/packages/SettingsLib/res/values-bn/strings.xml
index 743de50..c41a3e5 100644
--- a/packages/SettingsLib/res/values-bn/strings.xml
+++ b/packages/SettingsLib/res/values-bn/strings.xml
@@ -233,6 +233,7 @@
<string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"ব্লুটুথ অডিও কোডেক ট্রিগার করুন\nএটি বেছে নেওয়া আছে"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"ব্লুটুথ অডিওর নমুনা হার"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"ব্লুটুথ অডিও কোডেক ট্রিগার করুন\nএটি বেছে নেওয়া আছে: স্যাম্পল রেট"</string>
+ <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"গ্রে-আউট মানে যেখানে ফোন বা হেডসেট কাজ করে না"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"নমুনা প্রতি ব্লুটুথ অডিও বিট"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"ব্লুটুথ অডিও কোডেক ট্রিগার করুন\nএটি বেছে নেওয়া আছে: বিট্স পার স্যাম্পল"</string>
<string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"ব্লুটুথ অডিও চ্যানেল মোড"</string>
diff --git a/packages/SettingsLib/res/values-bs/strings.xml b/packages/SettingsLib/res/values-bs/strings.xml
index 75a4047..381fe4b 100644
--- a/packages/SettingsLib/res/values-bs/strings.xml
+++ b/packages/SettingsLib/res/values-bs/strings.xml
@@ -233,6 +233,7 @@
<string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Aktivirajte Bluetooth Audio Codec\nOdabir"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Brzina uzorkovanja za Bluetooth audio"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Aktivirajte Bluetooth Audio Codec\nOdabir: Brzina uzorkovanja"</string>
+ <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Ako je stavka nedostupna, to znači da je telefon ili slušalice ne podržavaju"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Bluetooth audio bitovi po uzorku"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Aktivirajte Bluetooth Audio Codec\nOdabir: Bitovi po uzorku"</string>
<string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Način Bluetooth audio kanala"</string>
diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml
index 8627cf3..3257dc5 100644
--- a/packages/SettingsLib/res/values-ca/strings.xml
+++ b/packages/SettingsLib/res/values-ca/strings.xml
@@ -233,6 +233,7 @@
<string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Activa el còdec d\'àudio per Bluetooth\nSelecció"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Freqüència de mostratge d’àudio per Bluetooth"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Activa el còdec d\'àudio per Bluetooth\nSelecció: freqüència de mostratge"</string>
+ <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Si una opció està ombrejada, vol dir que el telèfon o els auriculars no l\'admeten"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Bits per mostra de l\'àudio per Bluetooth"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Activa el còdec d\'àudio per Bluetooth\nSelecció: bits per mostra"</string>
<string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Mode de canal de l\'àudio per Bluetooth"</string>
diff --git a/packages/SettingsLib/res/values-cs/strings.xml b/packages/SettingsLib/res/values-cs/strings.xml
index 6fef07a..92ba7d1 100644
--- a/packages/SettingsLib/res/values-cs/strings.xml
+++ b/packages/SettingsLib/res/values-cs/strings.xml
@@ -233,6 +233,7 @@
<string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Spustit zvukový kodek Bluetooth\nVýběr"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Bluetooth Audio – vzorkovací frekvence"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Spustit zvukový kodek Bluetooth\nVýběr: vzorkovací frekvence"</string>
+ <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Zašedlé možnosti nejsou telefonem nebo náhlavní soupravou podporovány"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Bluetooth Audio – počet bitů na vzorek"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Spustit zvukový kodek Bluetooth\nVýběr: počet bitů na vzorek"</string>
<string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Bluetooth Audio – režim kanálu"</string>
diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml
index 80ee95e..d836b4a 100644
--- a/packages/SettingsLib/res/values-da/strings.xml
+++ b/packages/SettingsLib/res/values-da/strings.xml
@@ -233,6 +233,7 @@
<string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Udløs codec for Bluetooth-lyd\nValg"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Eksempelfrekvens for Bluetooth-lyd"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Udløs codec for Bluetooth-lyd\nValg: Samplingfrekvens"</string>
+ <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Nedtonede funktioner understøttes ikke af telefonen eller headsettet."</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Bit pr. eksempel for Bluetooth-lyd"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Udløs codec for Bluetooth-lyd\nValg: Bits pr. sampling"</string>
<string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Kanaltilstand for Bluetooth-lyd"</string>
diff --git a/packages/SettingsLib/res/values-de/strings.xml b/packages/SettingsLib/res/values-de/strings.xml
index 1cd1e55..dff8247 100644
--- a/packages/SettingsLib/res/values-de/strings.xml
+++ b/packages/SettingsLib/res/values-de/strings.xml
@@ -234,6 +234,7 @@
<string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Bluetooth-Audio-Codec auslösen\nAuswahl"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Bluetooth-Audio-Abtastrate"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Bluetooth-Audio-Codec auslösen\nAuswahl: Abtastrate"</string>
+ <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Wenn etwas ausgegraut ist, wird es nicht vom Smartphone oder Headset unterstützt"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Bluetooth-Audio/Bits pro Sample"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Bluetooth-Audio-Codec auslösen\nAuswahl: Bits pro Sample"</string>
<string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Bluetooth-Audiokanal-Modus"</string>
diff --git a/packages/SettingsLib/res/values-el/strings.xml b/packages/SettingsLib/res/values-el/strings.xml
index 7dee120..a86d259 100644
--- a/packages/SettingsLib/res/values-el/strings.xml
+++ b/packages/SettingsLib/res/values-el/strings.xml
@@ -233,6 +233,7 @@
<string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Ενεργοποίηση κωδικοποιητή ήχου Bluetooth\nΕπιλογή"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Ρυθμός δειγματοληψίας ήχου Bluetooth"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Ενεργοποίηση κωδικοποιητή ήχου Bluetooth\nΕπιλογή: Ρυθμός δειγματοληψίας"</string>
+ <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Οι γκριζαρισμένες επιλογές δεν υποστηρίζονται από τηλέφωνο ή ακουστικά"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Bit ανά δείγμα ήχου Bluetooth"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Ενεργοποίηση κωδικοποιητή ήχου Bluetooth\nΕπιλογή: Bit ανά δείγμα"</string>
<string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Λειτουργία καναλιού ήχου Bluetooth"</string>
diff --git a/packages/SettingsLib/res/values-en-rAU/strings.xml b/packages/SettingsLib/res/values-en-rAU/strings.xml
index ba9beb6..cadafce 100644
--- a/packages/SettingsLib/res/values-en-rAU/strings.xml
+++ b/packages/SettingsLib/res/values-en-rAU/strings.xml
@@ -233,6 +233,7 @@
<string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Trigger Bluetooth Audio Codec\nSelection"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Bluetooth audio sample rate"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Trigger Bluetooth Audio Codec\nSelection: Sample Rate"</string>
+ <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Grey-out means not supported by phone or headset"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Bluetooth audio bits per sample"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Trigger Bluetooth Audio Codec\nSelection: Bits Per Sample"</string>
<string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Bluetooth audio channel mode"</string>
diff --git a/packages/SettingsLib/res/values-en-rCA/strings.xml b/packages/SettingsLib/res/values-en-rCA/strings.xml
index ba9beb6..cadafce 100644
--- a/packages/SettingsLib/res/values-en-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-en-rCA/strings.xml
@@ -233,6 +233,7 @@
<string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Trigger Bluetooth Audio Codec\nSelection"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Bluetooth audio sample rate"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Trigger Bluetooth Audio Codec\nSelection: Sample Rate"</string>
+ <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Grey-out means not supported by phone or headset"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Bluetooth audio bits per sample"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Trigger Bluetooth Audio Codec\nSelection: Bits Per Sample"</string>
<string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Bluetooth audio channel mode"</string>
diff --git a/packages/SettingsLib/res/values-en-rGB/strings.xml b/packages/SettingsLib/res/values-en-rGB/strings.xml
index ba9beb6..cadafce 100644
--- a/packages/SettingsLib/res/values-en-rGB/strings.xml
+++ b/packages/SettingsLib/res/values-en-rGB/strings.xml
@@ -233,6 +233,7 @@
<string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Trigger Bluetooth Audio Codec\nSelection"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Bluetooth audio sample rate"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Trigger Bluetooth Audio Codec\nSelection: Sample Rate"</string>
+ <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Grey-out means not supported by phone or headset"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Bluetooth audio bits per sample"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Trigger Bluetooth Audio Codec\nSelection: Bits Per Sample"</string>
<string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Bluetooth audio channel mode"</string>
diff --git a/packages/SettingsLib/res/values-en-rIN/strings.xml b/packages/SettingsLib/res/values-en-rIN/strings.xml
index ba9beb6..cadafce 100644
--- a/packages/SettingsLib/res/values-en-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-en-rIN/strings.xml
@@ -233,6 +233,7 @@
<string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Trigger Bluetooth Audio Codec\nSelection"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Bluetooth audio sample rate"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Trigger Bluetooth Audio Codec\nSelection: Sample Rate"</string>
+ <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Grey-out means not supported by phone or headset"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Bluetooth audio bits per sample"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Trigger Bluetooth Audio Codec\nSelection: Bits Per Sample"</string>
<string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Bluetooth audio channel mode"</string>
diff --git a/packages/SettingsLib/res/values-en-rXC/strings.xml b/packages/SettingsLib/res/values-en-rXC/strings.xml
index 0f11774..444dbcb 100644
--- a/packages/SettingsLib/res/values-en-rXC/strings.xml
+++ b/packages/SettingsLib/res/values-en-rXC/strings.xml
@@ -233,6 +233,7 @@
<string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Trigger Bluetooth Audio Codec\nSelection"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Bluetooth Audio Sample Rate"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Trigger Bluetooth Audio Codec\nSelection: Sample Rate"</string>
+ <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Gray-out means not supported by phone or headset"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Bluetooth Audio Bits Per Sample"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Trigger Bluetooth Audio Codec\nSelection: Bits Per Sample"</string>
<string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Bluetooth Audio Channel Mode"</string>
diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml
index 41c817e..6a6f800 100644
--- a/packages/SettingsLib/res/values-es-rUS/strings.xml
+++ b/packages/SettingsLib/res/values-es-rUS/strings.xml
@@ -233,6 +233,7 @@
<string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Activar el códec de audio por Bluetooth\nSelección"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Frecuencia de muestreo del audio Bluetooth"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Activar el códec de audio por Bluetooth\nSelección: porcentaje de la muestra"</string>
+ <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Si la opción está inhabilitada, significa que el teléfono o los auriculares no la admiten"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Bits por muestra del audio Bluetooth"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Activar el códec de audio por Bluetooth\nSelección: bits por muestra"</string>
<string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Modo de canal del audio Bluetooth"</string>
diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml
index 897eaa3..e29773a 100644
--- a/packages/SettingsLib/res/values-es/strings.xml
+++ b/packages/SettingsLib/res/values-es/strings.xml
@@ -233,6 +233,7 @@
<string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Activar el códec de audio por Bluetooth\nSelección"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Frecuencia de muestreo de audio de Bluetooth"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Activar el códec de audio por Bluetooth\nSelección: frecuencia de muestreo"</string>
+ <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Si una opción aparece atenuada, no es compatible con el teléfono o los auriculares"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Bits por muestra del audio Bluetooth"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Activar el códec de audio por Bluetooth\nSelección: bits por muestra"</string>
<string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Modo de canal de audio de Bluetooth"</string>
diff --git a/packages/SettingsLib/res/values-et/strings.xml b/packages/SettingsLib/res/values-et/strings.xml
index 9b94222..f425e1e 100644
--- a/packages/SettingsLib/res/values-et/strings.xml
+++ b/packages/SettingsLib/res/values-et/strings.xml
@@ -233,6 +233,7 @@
<string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Bluetoothi helikodeki käivitamine\nValik"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Bluetoothi heli diskreetimissagedus"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Bluetoothi helikodeki käivitamine\nValik: diskreetimissagedus"</string>
+ <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Hallilt kuvamine tähendab, et telefon või peakomplekt seda ei toeta"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Bluetoothi heli bitte diskreedi kohta"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Bluetoothi helikodeki käivitamine\nValik: bittide arv diskreedi kohta"</string>
<string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Bluetoothi heli kanalirežiim"</string>
diff --git a/packages/SettingsLib/res/values-eu/strings.xml b/packages/SettingsLib/res/values-eu/strings.xml
index b0e4b26..e9810e5 100644
--- a/packages/SettingsLib/res/values-eu/strings.xml
+++ b/packages/SettingsLib/res/values-eu/strings.xml
@@ -233,6 +233,7 @@
<string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Abiarazi Bluetooth bidezko audio-kodeka\nHautapena"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Bluetooth bidezko audioaren lagin-abiadura"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Abiarazi Bluetooth bidezko audio-kodeka\nHautapena: lagin-abiadura"</string>
+ <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Kolore apalagoz agertzen bada, esan nahi du telefonoak edo entzungailuak ez duela onartzen"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Bluetooth bidezko audioaren lagin bakoitzeko bit kopurua"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Abiarazi Bluetooth bidezko audio-kodeka\nHautapena: lagin bakoitzeko bitak"</string>
<string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Bluetooth bidezko audioaren kanalaren modua"</string>
diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml
index 7298826..2f25ab2 100644
--- a/packages/SettingsLib/res/values-fa/strings.xml
+++ b/packages/SettingsLib/res/values-fa/strings.xml
@@ -233,6 +233,7 @@
<string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"راهاندازی کدک صوتی بلوتوثی\nانتخاب"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"سرعت نمونه بلوتوث صوتی"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"راهاندازی کدک صوتی بلوتوثی\nانتخاب: سرعت نمونه"</string>
+ <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"«خاکستری» به این معناست که تلفن یا هدست از آن پشتیبانی نمیکند"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"بیتهای بلوتوث صوتی در هر نمونه"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"راهاندازی کدک صوتی بلوتوثی\nانتخاب: تعداد بیت در نمونه"</string>
<string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"حالت کانال بلوتوث صوتی"</string>
diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml
index 6f58f03..a9904af 100644
--- a/packages/SettingsLib/res/values-fi/strings.xml
+++ b/packages/SettingsLib/res/values-fi/strings.xml
@@ -233,6 +233,7 @@
<string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Käynnistä Bluetooth-äänipakkaus\nValinta"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Bluetooth-ääninäytteen siirtonopeus"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Käynnistä Bluetooth-äänipakkaus\nValinta: esimerkkinopeus"</string>
+ <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Himmennys tarkoittaa, että puhelin tai kuulokemikrofoni ei tue tätä"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Bluetooth-äänen bittiä/näyte-arvo"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Käynnistä Bluetooth-äänipakkaus\nValinta: bittiä/näyte"</string>
<string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Bluetooth-äänen kanavatila"</string>
diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml
index a5526f3..0f1c213 100644
--- a/packages/SettingsLib/res/values-fr-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml
@@ -233,6 +233,7 @@
<string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Déclencher le codec audio Bluetooth\nSélection"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Taux d\'échantillonnage pour l\'audio Bluetooth"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Déclencher le codec audio Bluetooth\nSélection : taux d\'échantillonnage"</string>
+ <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Une option grisée signifie qu\'elle n\'est pas prise en charge par le téléphone ou par les écouteurs"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Bits par échantillon pour l\'audio Bluetooth"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Déclencher le codec audio Bluetooth\nSélection : bits par échantillon"</string>
<string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Mode de canal pour l\'audio Bluetooth"</string>
diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml
index 069825a..0bfb3c7 100644
--- a/packages/SettingsLib/res/values-fr/strings.xml
+++ b/packages/SettingsLib/res/values-fr/strings.xml
@@ -234,6 +234,7 @@
<string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Critère pour déclencher la sélection du codec audio\nBluetooth"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Taux d\'échantillonnage audio Bluetooth"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Critère de sélection du codec audio\nBluetooth : taux d\'échantillonnage"</string>
+ <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Si le codec est grisé, c\'est qu\'il n\'est pas compatible avec le téléphone ou le casque"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Bits par échantillon pour l\'audio Bluetooth"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Critère de sélection du codec audio\nBluetooth : nombre de bits par échantillon"</string>
<string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Mode de chaîne de l\'audio Bluetooth"</string>
diff --git a/packages/SettingsLib/res/values-gl/strings.xml b/packages/SettingsLib/res/values-gl/strings.xml
index eaab027..213d33a 100644
--- a/packages/SettingsLib/res/values-gl/strings.xml
+++ b/packages/SettingsLib/res/values-gl/strings.xml
@@ -233,6 +233,7 @@
<string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Activar códec de audio por Bluetooth\nSelección"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Taxa de mostra de audio por Bluetooth"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Activar códec de audio por Bluetooth\nSelección: taxa de mostra"</string>
+ <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Os elementos deshabilitados non son compatibles co teléfono ou cos auriculares"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Bits por mostra de audio por Bluetooth"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Activar códec de audio por Bluetooth\nSelección: bits por mostra"</string>
<string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Modo de canle de audio por Bluetooth"</string>
diff --git a/packages/SettingsLib/res/values-gu/strings.xml b/packages/SettingsLib/res/values-gu/strings.xml
index 00fd024..8192d47 100644
--- a/packages/SettingsLib/res/values-gu/strings.xml
+++ b/packages/SettingsLib/res/values-gu/strings.xml
@@ -233,6 +233,7 @@
<string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"બ્લૂટૂથ ઑડિઓ કોડેક\nપસંદગી ટ્રિગર કરો"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"બ્લૂટૂથ ઑડિઓ નમૂના દર"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"બ્લૂટૂથ ઑડિઓ કોડેક\nપસંદગી ટ્રિગર કરો: નમૂના રેટ"</string>
+ <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"નિષ્ક્રિય હોવાનો અર્થ એ છે કે ફોન અથવા હૅડસેટ દ્વારા સપોર્ટ આપવામાં આવતો નથી"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"નમૂના દીઠ બ્લૂટૂથ ઑડિઓ બિટ"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"બ્લૂટૂથ ઑડિઓ કોડેક\nપસંદગી ટ્રિગર કરો: નમૂના દીઠ બિટ"</string>
<string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"બ્લૂટૂથ ઑડિઓ ચેનલ મોડ"</string>
diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml
index 96aec94..207a479 100644
--- a/packages/SettingsLib/res/values-hi/strings.xml
+++ b/packages/SettingsLib/res/values-hi/strings.xml
@@ -233,6 +233,7 @@
<string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"ब्लूटूथ ऑडियो कोडेक का\nविकल्प चालू करें"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"ब्लूटूथ ऑडियो नमूना दर"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"ब्लूटूथ ऑडियो कोडेक का\nयह विकल्प चालू करें: सैंपल की दर"</string>
+ <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"धूसर किया गया का मतलब है कि फ़ोन या हेडसेट पर काम नहीं करता"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"ब्लूटूथ ऑडियो बिट प्रति नमूना"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"ब्लूटूथ ऑडियो कोडेक का\nयह विकल्प चालू करें: हर सैंपल के लिए बिट की संख्या"</string>
<string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"ब्लूटूथ ऑडियो चैनल मोड"</string>
diff --git a/packages/SettingsLib/res/values-hr/strings.xml b/packages/SettingsLib/res/values-hr/strings.xml
index 6df46ca..97a5862 100644
--- a/packages/SettingsLib/res/values-hr/strings.xml
+++ b/packages/SettingsLib/res/values-hr/strings.xml
@@ -233,6 +233,7 @@
<string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Pokreni odabir kodeka za Bluetooth\nAudio"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Brzina uzorka za Bluetooth Audio"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Pokreni odabir kodeka za Bluetooth\nAudio: brzina uzorkovanja"</string>
+ <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Ako je stavka siva, znači da je telefon ili slušalice ne podržavaju"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Bitovi po uzorku za Bluetooth Audio"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Pokreni odabir kodeka za Bluetooth\nAudio: bitovi po uzorku"</string>
<string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Način kanala za Bluetooth Audio"</string>
diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml
index 6b5b05e..cba6c65 100644
--- a/packages/SettingsLib/res/values-hu/strings.xml
+++ b/packages/SettingsLib/res/values-hu/strings.xml
@@ -233,6 +233,7 @@
<string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Bluetooth-hangkodek aktiválása\nKiválasztás"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Bluetooth hang – mintavételezési gyakoriság"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Bluetooth-hangkodek aktiválása\nKiválasztás: Mintavételezési gyakoriság"</string>
+ <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"A kiszürkítés azt jelenti, hogy nem támogatja telefon vagy headset"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Bluetooth hang – bit/minta"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Bluetooth-hangkodek aktiválása\nKiválasztás: Bit/minta"</string>
<string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Bluetooth hang – Csatornamód"</string>
diff --git a/packages/SettingsLib/res/values-hy/strings.xml b/packages/SettingsLib/res/values-hy/strings.xml
index c4002b9..a76c960 100644
--- a/packages/SettingsLib/res/values-hy/strings.xml
+++ b/packages/SettingsLib/res/values-hy/strings.xml
@@ -233,6 +233,7 @@
<string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Գործարկել Bluetooth աուդիո կոդեկը\nԸնտրություն"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Bluetooth աուդիոյի ընդհատավորման հաճախականությունը"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Գործարկել Bluetooth աուդիո կոդեկը\nԸնտրություն՝ ընդհատավորման հաճախականություն"</string>
+ <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Եթե տարրը մոխրագույն է, նշանակում է, որ չի աջակցվում հեռախոսի համ ականջակալի կողմից։"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Bluetooth աուդիո, բիթ / նմուշ"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Գործարկել Bluetooth աուդիո կոդեկը\nԸնտրություն՝ բիթ/նմուշ"</string>
<string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Bluetooth աուդիո կապուղու ռեժիմը"</string>
diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml
index 753f225..0feae4e 100644
--- a/packages/SettingsLib/res/values-in/strings.xml
+++ b/packages/SettingsLib/res/values-in/strings.xml
@@ -233,6 +233,7 @@
<string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Aktifkan Codec Audio Bluetooth\nPilihan"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Frekuensi Sampel Audio Bluetooth"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Aktifkan Codec Audio Bluetooth\nPilihan: Frekuensi Sampel"</string>
+ <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Berwarna abu-abu artinya tidak didukung oleh ponsel atau headset"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Bit Per Sampel Audio Bluetooth"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Aktifkan Codec Audio Bluetooth\nPilihan: Bit Per Sampel"</string>
<string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Mode Channel Audio Bluetooth"</string>
diff --git a/packages/SettingsLib/res/values-is/strings.xml b/packages/SettingsLib/res/values-is/strings.xml
index b1d40bf..d45f433 100644
--- a/packages/SettingsLib/res/values-is/strings.xml
+++ b/packages/SettingsLib/res/values-is/strings.xml
@@ -233,6 +233,7 @@
<string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Virkja Bluetooth-hljóðkóðara\nVal"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Bluetooth hljóðtökutíðni"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Virkja Bluetooth-hljóðkóðara\nVal: upptökutíðni"</string>
+ <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Óvirkt þýðir að síminn eða höfuðtólin styðja þetta ekki"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Bluetooth hljóðbitar í úrtaki"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Virkja Bluetooth-hljóðkóðara\nVal: bitar í úrtaki"</string>
<string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Hljóðrásarstilling Bluetooth"</string>
diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml
index 7f2bd3e..fe111fc 100644
--- a/packages/SettingsLib/res/values-it/strings.xml
+++ b/packages/SettingsLib/res/values-it/strings.xml
@@ -233,6 +233,7 @@
<string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Attiva il codec audio Bluetooth\nSelezione"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Frequenza campionamento audio Bluetooth"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Attiva il codec audio Bluetooth\nSelezione: Frequenza di campionamento"</string>
+ <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Se il codec non è selezionabile significa che non è supportato dal telefono o dalle cuffie"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Bit per campione dell\'audio Bluetooth"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Attiva il codec audio Bluetooth\nSelezione: bit per campione"</string>
<string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Modalità canale audio Bluetooth"</string>
diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml
index bdd1bab..8b47c54 100644
--- a/packages/SettingsLib/res/values-iw/strings.xml
+++ b/packages/SettingsLib/res/values-iw/strings.xml
@@ -233,6 +233,7 @@
<string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"הפעלת Codec אודיו ל-Bluetooth\nבחירה"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"קצב דגימה של אודיו ל-Bluetooth"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"הפעלת Codec אודיו ל-Bluetooth\nבחירה: קצב דגימה"</string>
+ <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"כשזה מופיע באפור, אין לזה תמיכה בטלפון או באוזניות"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"מספר סיביות לדגימה באודיו ל-Bluetooth"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"הפעלת Codec אודיו ל-Bluetooth\nבחירה: סיביות לדגימה"</string>
<string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"מצב של ערוץ אודיו ל-Bluetooth"</string>
diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml
index a6192a4..c955a39 100644
--- a/packages/SettingsLib/res/values-ja/strings.xml
+++ b/packages/SettingsLib/res/values-ja/strings.xml
@@ -233,6 +233,7 @@
<string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Bluetooth オーディオ コーデックを起動\n選択"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Bluetooth オーディオ サンプルレート"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Bluetooth オーディオ コーデックを起動\n選択: サンプルレート"</string>
+ <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"グレー表示のコーデックは、スマートフォンまたはヘッドセットが対応していません"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"サンプルあたりの Bluetooth オーディオ ビット"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Bluetooth オーディオ コーデックを起動\n選択: サンプルあたりのビット数"</string>
<string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Bluetooth オーディオ チャンネル モード"</string>
diff --git a/packages/SettingsLib/res/values-ka/strings.xml b/packages/SettingsLib/res/values-ka/strings.xml
index a3633f6..d8fda4b 100644
--- a/packages/SettingsLib/res/values-ka/strings.xml
+++ b/packages/SettingsLib/res/values-ka/strings.xml
@@ -233,6 +233,7 @@
<string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Bluetooth-ის აუდიო კოდეკის გაშვება\nარჩევანი"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Bluetooth აუდიოს დისკრეტიზაციის სიხშირე"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Bluetooth-ის აუდიო კოდეკის გაშვება\nარჩევანი: ნიმუშთა მაჩვენებელი"</string>
+ <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"არააქტიური ნიშნავს, რომ ტელეფონის ან ყურსასმენის მიერ მხარდაჭერილი არ არის"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Bluetooth აუდიოს ბიტების რაოდენობა ნიმუშზე"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Bluetooth-ის აუდიო კოდეკის გაშვება\nარჩევანი: ბიტები ნიმუშზე"</string>
<string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Bluetooth აუდიოს არხის რეჟიმი"</string>
diff --git a/packages/SettingsLib/res/values-kk/strings.xml b/packages/SettingsLib/res/values-kk/strings.xml
index 0962e55..025532d 100644
--- a/packages/SettingsLib/res/values-kk/strings.xml
+++ b/packages/SettingsLib/res/values-kk/strings.xml
@@ -233,6 +233,7 @@
<string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Bluetooth аудиокодегін іске қосу\nТаңдау"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Bluetooth арқылы дыбыс іріктеу жиілігі"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Bluetooth аудиокодегін іске қосу\nТаңдау: іріктеу жылдамдығы"</string>
+ <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Сұр түсті болса, бұл оған телефонда не гарнитурада қолдау көрсетілмейтінін білдіреді."</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Bluetooth арқылы дыбыстың разрядтылық мөлшері"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Bluetooth аудиокодегін іске қосу\nТаңдау: разрядтылық"</string>
<string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Bluetooth дыбыстық арна режимі"</string>
diff --git a/packages/SettingsLib/res/values-km/strings.xml b/packages/SettingsLib/res/values-km/strings.xml
index 45620e8..e9f5ab0 100644
--- a/packages/SettingsLib/res/values-km/strings.xml
+++ b/packages/SettingsLib/res/values-km/strings.xml
@@ -233,6 +233,7 @@
<string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"ជំរុញការជ្រើសរើសកូឌិកសំឡេង\nប៊្លូធូស"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"អត្រាគំរូសំឡេងប៊្លូធូស"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"ជំរុញការជ្រើសរើសកូឌិកសំឡេង\nប៊្លូធូស៖ អត្រាគំរូ"</string>
+ <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"ការកំណត់ជាពណ៌ប្រផេះមានន័យថាទូរសព្ទ ឬកាសមិនស្គាល់ទេ"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"កម្រិតប៊ីតក្នុងមួយគំរូនៃសំឡេងប៊្លូធូស"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"ជំរុញការជ្រើសរើសកូឌិកសំឡេង\nប៊្លូធូស៖ កម្រិតប៊ីតក្នុងមួយគំរូ"</string>
<string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"មុខងាររលកសញ្ញាសំឡេងប៊្លូធូស"</string>
diff --git a/packages/SettingsLib/res/values-kn/strings.xml b/packages/SettingsLib/res/values-kn/strings.xml
index 1fc2e4a..4feccaf 100644
--- a/packages/SettingsLib/res/values-kn/strings.xml
+++ b/packages/SettingsLib/res/values-kn/strings.xml
@@ -233,6 +233,7 @@
<string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"ಬ್ಲೂಟೂತ್ ಆಡಿಯೋ ಕೋಡೆಕ್ ಅನ್ನು ಟ್ರಿಗ್ಗರ್ ಮಾಡಿ\nಆಯ್ಕೆ"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"ಬ್ಲೂಟೂತ್ ಆಡಿಯೋ ಮಾದರಿ ದರ"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"ಬ್ಲೂಟೂತ್ ಆಡಿಯೋ ಕೋಡೆಕ್ ಅನ್ನು ಟ್ರಿಗ್ಗರ್ ಮಾಡಿ\nಆಯ್ಕೆ: ಮಾದರಿ ರೇಟ್"</string>
+ <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"ಬೂದುಬಣ್ಣಕ್ಕೆ ತಿರುಗುವುದು ಎಂದರೆ ಫೋನ್ ಅಥವಾ ಹೆಡ್ಸೆಟ್ ಬೆಂಬಲಿಸುವುದಿಲ್ಲ ಎಂದರ್ಥ"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"ಬ್ಲೂಟೂತ್ ಆಡಿಯೊ ಬಿಟ್ಸ್ನ ಪ್ರತಿ ಮಾದರಿ"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"ಬ್ಲೂಟೂತ್ ಆಡಿಯೋ ಕೋಡೆಕ್ ಅನ್ನು ಟ್ರಿಗ್ಗರ್ ಮಾಡಿ \nಆಯ್ಕೆ: ಬಿಟ್ಸ್ನ ಪ್ರತಿ ಮಾದರಿ"</string>
<string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"ಬ್ಲೂಟೂತ್ ಆಡಿಯೋ ಚಾನೆಲ್ ಮೋಡ್"</string>
diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml
index 8e7c697..4707ef8 100644
--- a/packages/SettingsLib/res/values-ko/strings.xml
+++ b/packages/SettingsLib/res/values-ko/strings.xml
@@ -233,6 +233,7 @@
<string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"블루투스 오디오 코덱 실행\n선택"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"블루투스 오디오 샘플링 비율"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"블루투스 오디오 코덱 실행\n선택: 샘플링 비율"</string>
+ <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"비활성화되어 있으면 스마트폰 또는 헤드셋에서 지원하지 않음을 의미함"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"블루투스 오디오 샘플당 비트"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"블루투스 오디오 코덱 실행\n선택: 샘플당 비트"</string>
<string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"블루투스 오디오 채널 모드"</string>
diff --git a/packages/SettingsLib/res/values-ky/strings.xml b/packages/SettingsLib/res/values-ky/strings.xml
index 18a1468..2197a9f 100644
--- a/packages/SettingsLib/res/values-ky/strings.xml
+++ b/packages/SettingsLib/res/values-ky/strings.xml
@@ -233,6 +233,7 @@
<string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Bluetooth Audio кодегин иштетүү\nТандоо"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Bluetooth аудио үлгүсүнүн ылдамдыгы"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Bluetooth Audio кодегин иштетүү\nТандоо: Үлгү жыштыгы"</string>
+ <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Боз түс менен белгиленген кодек – бул телефондо же гарнитурада колдоого алынбайт дегенди билдирет"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Бир үлгүдөгү Bluetooth аудио биттери"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Bluetooth Audio кодегин иштетүү\nТандоо: Бир үлгүдөгү биттер"</string>
<string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Bluetooth аудио каналынын режими"</string>
diff --git a/packages/SettingsLib/res/values-lo/strings.xml b/packages/SettingsLib/res/values-lo/strings.xml
index 808d5a7..de3f644 100644
--- a/packages/SettingsLib/res/values-lo/strings.xml
+++ b/packages/SettingsLib/res/values-lo/strings.xml
@@ -233,6 +233,7 @@
<string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"ເປີດໃຊ້ Bluetooth Audio Codec\nການເລືອກ"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Bluetooth Audio Sample Rate"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"ເປີດໃຊ້ Bluetooth Audio Codec\nການເລືອກ: Sample Rate"</string>
+ <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"ສ່ວນທີ່ເປັນສີເທົາໝາຍຄວາມວ່າບໍ່ຮອງຮັບໂດຍໂທລະສັບ ຫຼື ຊຸດຫູຟັງ"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Bluetooth Audio Bits Per Sample"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"ເປີດໃຊ້ Bluetooth Audio Codec\nການເລືອກ: Bits Per Sample"</string>
<string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"ໂໝດຊ່ອງສຽງ Bluetooth"</string>
diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml
index 78d1b1b..6157a87 100644
--- a/packages/SettingsLib/res/values-lt/strings.xml
+++ b/packages/SettingsLib/res/values-lt/strings.xml
@@ -233,6 +233,7 @@
<string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Suaktyvinti „Bluetooth“ garso kodeką\nPasirinkimas"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"„Bluetooth“ garso pavyzdžio dažnis"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Suaktyvinti „Bluetooth“ garso kodeką\nPasirinkimas: pavyzdžio dažnis"</string>
+ <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Pilka spalva reiškia, kad telefonas arba ausinės nepalaiko tos funkcijos"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"„Bluetooth“ garso įrašo bitų skaičius pavyzdyje"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Suaktyvinti „Bluetooth“ garso kodeką\nPasirinkimas: bitų skaičius pavyzdyje"</string>
<string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"„Bluetooth“ garso kanalo režimas"</string>
diff --git a/packages/SettingsLib/res/values-lv/strings.xml b/packages/SettingsLib/res/values-lv/strings.xml
index 0ae10aa..51b909c 100644
--- a/packages/SettingsLib/res/values-lv/strings.xml
+++ b/packages/SettingsLib/res/values-lv/strings.xml
@@ -233,6 +233,7 @@
<string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Aktivizēt Bluetooth audio kodeku\nAtlase"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Bluetooth audio iztveršanas ātrums"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Aktivizēt Bluetooth audio kodeku\nAtlase: iztveršanas ātrums"</string>
+ <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Ja vienums ir pelēkots, tas netiek atbalstīts tālrunī vai austiņās."</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Bluetooth audio bitu skaits iztvērumā"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Aktivizēt Bluetooth audio kodeku\nAtlase: bitu skaitu iztvērumā"</string>
<string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Bluetooth audio kanāla režīms"</string>
diff --git a/packages/SettingsLib/res/values-mk/strings.xml b/packages/SettingsLib/res/values-mk/strings.xml
index 9850ac5..9a0d2da 100644
--- a/packages/SettingsLib/res/values-mk/strings.xml
+++ b/packages/SettingsLib/res/values-mk/strings.xml
@@ -233,6 +233,7 @@
<string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Вклучете го аудио кодекот преку Bluetooth\nСелекција"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Стапка на семпл преку Bluetooth"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Вклучете го аудио кодекот преку Bluetooth\nСелекција: стапка на примерокот"</string>
+ <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Ако е сиво, значи дека не е поддржано од телефонот или од слушалките"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Аудио бит-по-семпл преку Bluetooth"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Вклучете го аудио кодекот преку Bluetooth\nСелекција: бит-по-семпл"</string>
<string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Режим на канал за аудио преку Bluetooth"</string>
diff --git a/packages/SettingsLib/res/values-ml/strings.xml b/packages/SettingsLib/res/values-ml/strings.xml
index 2692a30..e9558fc 100644
--- a/packages/SettingsLib/res/values-ml/strings.xml
+++ b/packages/SettingsLib/res/values-ml/strings.xml
@@ -233,6 +233,7 @@
<string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Bluetooth Audio Codec\nSelection ട്രിഗ്ഗര് ചെയ്യുക"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Bluetooth ഓഡിയോ സാമ്പിൾ നിരക്ക്"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Bluetooth Audio Codec\nSelection ട്രിഗ്ഗര് ചെയ്യുക: സാമ്പിൾ റേറ്റ്"</string>
+ <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"ചാരനിറത്തിലാക്കിയിട്ടുണ്ടെങ്കിൽ, ഫോണോ ഹെഡ്സെറ്റോ പിന്തുണയ്ക്കുന്നില്ലെന്നാണ് അർത്ഥം"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"പ്രതി സാമ്പിളിലെ Bluetooth ഓഡിയോ ബിറ്റ് നി"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Bluetooth Audio Codec\nSelection ട്രിഗ്ഗര് ചെയ്യുക: ഓരോ സാമ്പിളിനുള്ള ബിറ്റുകൾ"</string>
<string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Bluetooth ഓഡിയോ ചാനൽ മോഡ്"</string>
diff --git a/packages/SettingsLib/res/values-mn/strings.xml b/packages/SettingsLib/res/values-mn/strings.xml
index aa4ec76..4997f0b 100644
--- a/packages/SettingsLib/res/values-mn/strings.xml
+++ b/packages/SettingsLib/res/values-mn/strings.xml
@@ -233,6 +233,7 @@
<string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Bluetooth-н аудио кодлогчийг өдөөх\nСонголт"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Bluetooth аудио жишээний үнэлгээ"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Bluetooth-н аудио кодлогчийг өдөөх\nСонголт: Жишээ үнэлгээ"</string>
+ <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Идэвхгүй саарал байх нь утас эсвэл чихэвч дэмждэггүй болохыг илтгэнэ"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Жишээ тутмын Bluetooth аудионы бит"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Bluetooth-н аудио кодлогчийг өдөөх\nСонголт: Жишээ бүрийн бит"</string>
<string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Bluetooth аудио сувгийн горим"</string>
diff --git a/packages/SettingsLib/res/values-mr/strings.xml b/packages/SettingsLib/res/values-mr/strings.xml
index 966cdff..1dbd592 100644
--- a/packages/SettingsLib/res/values-mr/strings.xml
+++ b/packages/SettingsLib/res/values-mr/strings.xml
@@ -233,6 +233,7 @@
<string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"ब्लूटूथ ऑडिओ Codec ट्रिगर करा\nनिवड"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"ब्लूटूथ ऑडिओ पॅटर्न दर"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"ब्लूटूथ ऑडिओ Codec ट्रिगर करा\nनिवड: नमुना दर"</string>
+ <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"फोन किंवा हेडसेटला सपोर्ट करत नाही म्हणजे ती निकामी झाली आहे"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"प्रति पॅटर्न ब्लूटूध ऑडिओ बिट"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"ब्लूटूथ ऑडिओ Codec ट्रिगर करा\nनिवड: बिट प्रति नमुना"</string>
<string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"ब्लूटूथ ऑडिओ चॅनेल मोड"</string>
diff --git a/packages/SettingsLib/res/values-ms/strings.xml b/packages/SettingsLib/res/values-ms/strings.xml
index 88d7c7d..790480d 100644
--- a/packages/SettingsLib/res/values-ms/strings.xml
+++ b/packages/SettingsLib/res/values-ms/strings.xml
@@ -233,6 +233,7 @@
<string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Cetuskan Codec Audio Bluetooth\nPilihan"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Kadar Sampel Audio Bluetooth"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Cetuskan Codec Audio Bluetooth\nPilihan: Kadar Sampel"</string>
+ <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Bahagian yang dikelabukan bermaksud tidak disokong oleh telefon atau set kepala"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Bit Per Sampel Audio Bluetooth"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Cetuskan Codec Audio Bluetooth\nPilihan: Bit Per Sampel"</string>
<string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Mod Saluran Audio Bluetooth"</string>
diff --git a/packages/SettingsLib/res/values-my/strings.xml b/packages/SettingsLib/res/values-my/strings.xml
index 6dfd290..dc81d05 100644
--- a/packages/SettingsLib/res/values-my/strings.xml
+++ b/packages/SettingsLib/res/values-my/strings.xml
@@ -233,6 +233,7 @@
<string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"ဘလူးတုသ် အသံ LDAC ကိုးဒက်ခ် ဖွင့်ခြင်း\nရွေးချယ်မှု"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"ဘလူးတုသ်အသံနမူနာနှုန်း"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"ဘလူးတုသ် အသံ ကိုးဒက်ခ် ဖွင့်ခြင်း\nရွေးချယ်မှု- နမူနာနှုန်း"</string>
+ <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"မီးခိုးရောင် ခြယ်ထားခြင်းသည် ဖုန်း သို့မဟုတ် မိုက်ခွက်ပါနားကြပ်မှ ပံ့ပိုးထားမှုမရှိခြင်းကို ဆိုလိုသည်။"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"နမူနာတစ်ခုစီတွင် ပါဝင်သော ဘလူးတုသ်အသံပမာဏ Bits"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"ဘလူးတုသ် အသံ ကိုးဒက်ခ် ဖွင့်ခြင်း\nရွေးချယ်မှု- နမူနာတစ်ခုစီအတွက် Bits"</string>
<string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"ဘလူးတုသ်အသံချန်နယ်မုဒ်"</string>
diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml
index 760c409..d0e4966 100644
--- a/packages/SettingsLib/res/values-nb/strings.xml
+++ b/packages/SettingsLib/res/values-nb/strings.xml
@@ -233,6 +233,7 @@
<string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Utløs kodek for Bluetooth-lyd\nValg"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Samplefrekvens for Bluetooth-lyd"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Utløs kodek for Bluetooth-lyd\nValg: samplefrekvens"</string>
+ <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Hvis den er nedtonet, støttes den ikke av telefonen eller hodetelefonene"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Bits per sample for Bluetooth-lyd"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Utløs kodek for Bluetooth-lyd\nValg: bits per sample"</string>
<string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Kanalmodus for Bluetooth-lyd"</string>
diff --git a/packages/SettingsLib/res/values-ne/strings.xml b/packages/SettingsLib/res/values-ne/strings.xml
index 77f87ff..d8ed4cb 100644
--- a/packages/SettingsLib/res/values-ne/strings.xml
+++ b/packages/SettingsLib/res/values-ne/strings.xml
@@ -233,6 +233,7 @@
<string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"ब्लुटुथ अडियो कोडेक ट्रिगर गर्नुहोस्\nचयन"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"ब्लुटुथ अडियोको नमूना दर"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"ब्लुटुथ अडियो कोडेक ट्रिगर गर्नुहोस्\nचयन: नमुना दर"</string>
+ <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"खरानी रङले भरिएको भन्नाले फोन वा हेडसेटले समर्थन नगरेको बुझाउँछ"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"प्रति नमूना ब्लुटुथ अडियोका बिटहरू"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"ब्लुटुथ अडियो कोडेक ट्रिगर गर्नुहोस्\nचयन: बिट प्रति नमुना"</string>
<string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"ब्लुटुथ अडियो च्यानलको मोड"</string>
diff --git a/packages/SettingsLib/res/values-nl/strings.xml b/packages/SettingsLib/res/values-nl/strings.xml
index 55f56d9..d5ce540 100644
--- a/packages/SettingsLib/res/values-nl/strings.xml
+++ b/packages/SettingsLib/res/values-nl/strings.xml
@@ -233,6 +233,7 @@
<string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Codec voor Bluetooth-audio activeren\nSelectie"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Sample rate van Bluetooth-audio"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Codec voor Bluetooth-audio activeren\nSelectie: Bemonsteringsfrequentie"</string>
+ <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Uitgegrijsd betekent niet ondersteund door telefoon of headset"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Bits per sample voor Bluetooth-audio"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Codec voor Bluetooth-audio activeren\nSelectie: Bits per sample"</string>
<string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Kanaalmodus voor Bluetooth-audio"</string>
diff --git a/packages/SettingsLib/res/values-or/strings.xml b/packages/SettingsLib/res/values-or/strings.xml
index 98c302d..024bd3c 100644
--- a/packages/SettingsLib/res/values-or/strings.xml
+++ b/packages/SettingsLib/res/values-or/strings.xml
@@ -233,6 +233,7 @@
<string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"ବ୍ଲୁଟୂଥ୍ ଅଡିଓ କୋଡେକ୍\nସିଲେକ୍ସନ୍କୁ ଗତିଶୀଳ କରନ୍ତୁ"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"ବ୍ଲୁଟୂଥ୍ ଅଡିଓ ସାମ୍ପଲ୍ ରେଟ୍"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"ବ୍ଲୁଟୂଥ୍ ଅଡିଓ କୋଡେକ୍\nସିଲେକ୍ସନ୍କୁ ଗତିଶୀଳ କରନ୍ତୁ: ସାମ୍ପଲ୍ ରେଟ୍"</string>
+ <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"ଗ୍ରେ-ଆଉଟ୍ ଅର୍ଥ ଫୋନ୍ କିମ୍ବା ହେଡ୍ସେଟ୍ରେ ସମର୍ଥନ କରୁନାହିଁ"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"ନମୁନା ପିଛା ବ୍ଲୁଟୂଥ୍ ଅଡିଓ ବିଟ୍ସ"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"ବ୍ଲୁଟୂଥ୍ ଅଡିଓ କୋଡେକ୍\nସିଲେକ୍ସନ୍କୁ ଗତିଶୀଳ କରନ୍ତୁ: ନମୁନା ପିଛା ବିଟ୍ସ"</string>
<string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"ବ୍ଲୁଟୂଥ୍ ଅଡିଓ ଚ୍ୟାନେଲ୍ ମୋଡ୍"</string>
diff --git a/packages/SettingsLib/res/values-pa/strings.xml b/packages/SettingsLib/res/values-pa/strings.xml
index 525ad2e..042bbf7 100644
--- a/packages/SettingsLib/res/values-pa/strings.xml
+++ b/packages/SettingsLib/res/values-pa/strings.xml
@@ -233,6 +233,7 @@
<string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"ਬਲੂਟੁੱਥ ਆਡੀਓ ਕੋਡੇਕ\nਚੋਣ ਨੂੰ ਟ੍ਰਿਗਰ ਕਰੋ"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"ਬਲੂਟੁੱਥ ਆਡੀਓ ਸੈਂਪਲ ਰੇਟ"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"ਬਲੂਟੁੱਥ ਆਡੀਓ ਕੋਡੇਕ\nਚੋਣ ਨੂੰ ਟ੍ਰਿਗਰ ਕਰੋ: ਸੈਂਪਲ ਰੇਟ"</string>
+ <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"ਅਯੋਗ ਦਾ ਮਤਲਬ ਹੈ ਫ਼ੋਨ ਜਾਂ ਹੈੱਡਸੈੱਟ ਵੱਲੋਂ ਸਮਰਥਿਤ ਨਹੀਂ ਹੈ"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"ਪ੍ਰਤੀ ਸੈਂਪਲ ਬਲੂਟੁੱਥ ਆਡੀਓ ਬਿਟਾਂ"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"ਬਲੂਟੁੱਥ ਆਡੀਓ ਕੋਡੇਕ\nਚੋਣ ਨੂੰ ਟ੍ਰਿਗਰ ਕਰੋ: ਪ੍ਰਤੀ ਸੈਂਪਲ ਬਿਟਾਂ"</string>
<string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"ਬਲੂਟੁੱਥ ਆਡੀਓ ਚੈਨਲ ਮੋਡ"</string>
diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml
index 69ebc59..7856679 100644
--- a/packages/SettingsLib/res/values-pl/strings.xml
+++ b/packages/SettingsLib/res/values-pl/strings.xml
@@ -233,6 +233,7 @@
<string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Uruchom kodek dźwięku Bluetooth\nWybór"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Dźwięk Bluetooth – współczynnik próbkowania"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Uruchom kodek dźwięku Bluetooth\nWybór: częstotliwość próbkowania"</string>
+ <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Elementy wyszarzone nie są obsługiwane przez telefon lub zestaw słuchawkowy"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Dźwięk Bluetooth – liczba bitów na próbkę"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Uruchom kodek dźwięku Bluetooth\nWybór: liczba bitów na próbkę"</string>
<string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Dźwięk Bluetooth – tryb kanału"</string>
diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml
index 62017f1..6a32200 100644
--- a/packages/SettingsLib/res/values-pt-rBR/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml
@@ -233,6 +233,7 @@
<string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Acionar codec de áudio Bluetooth\nSeleção"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Taxa de amostra do áudio Bluetooth"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Acionar codec de áudio Bluetooth\nSeleção: taxa de amostra"</string>
+ <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Os itens esmaecidos não são compatíveis com o smartphone ou o fone de ouvido"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Bits por amostra do áudio Bluetooth"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Acionar codec de áudio Bluetooth\nSeleção: bits por amostra"</string>
<string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Modo de canal de áudio Bluetooth"</string>
diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml
index 8304768..caf1ba4 100644
--- a/packages/SettingsLib/res/values-pt-rPT/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml
@@ -233,6 +233,7 @@
<string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Acionar o codec de áudio Bluetooth\nSeleção"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Taxa de amostragem de áudio Bluetooth"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Acionar o codec de áudio Bluetooth\nSeleção: frequência de amostragem"</string>
+ <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Se estiver assinalado a cinzento, significa que não é suportado pelo telemóvel ou pelos auscultadores com microfone integrado"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Bits por amostra de áudio Bluetooth"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Acionar o codec de áudio Bluetooth\nSeleção: bits por amostra"</string>
<string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Modo de canal áudio Bluetooth"</string>
diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml
index 62017f1..6a32200 100644
--- a/packages/SettingsLib/res/values-pt/strings.xml
+++ b/packages/SettingsLib/res/values-pt/strings.xml
@@ -233,6 +233,7 @@
<string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Acionar codec de áudio Bluetooth\nSeleção"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Taxa de amostra do áudio Bluetooth"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Acionar codec de áudio Bluetooth\nSeleção: taxa de amostra"</string>
+ <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Os itens esmaecidos não são compatíveis com o smartphone ou o fone de ouvido"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Bits por amostra do áudio Bluetooth"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Acionar codec de áudio Bluetooth\nSeleção: bits por amostra"</string>
<string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Modo de canal de áudio Bluetooth"</string>
diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml
index 50ea4a0..38cd60f 100644
--- a/packages/SettingsLib/res/values-ro/strings.xml
+++ b/packages/SettingsLib/res/values-ro/strings.xml
@@ -233,6 +233,7 @@
<string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Declanșați codecul audio Bluetooth\nSelecție"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Rată de eșantionare audio Bluetooth"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Declanșați codecul audio Bluetooth\nSelecție: rată de eșantionare"</string>
+ <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"O opțiune inactivă înseamnă incompatibilitate cu telefonul sau setul căști-microfon"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Biți audio Bluetooth per eșantion"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Declanșați codecul audio Bluetooth\nSelecție: biți per eșantion"</string>
<string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Modul canal audio Bluetooth"</string>
diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml
index 0582a0c..124bf13 100644
--- a/packages/SettingsLib/res/values-ru/strings.xml
+++ b/packages/SettingsLib/res/values-ru/strings.xml
@@ -233,6 +233,7 @@
<string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Запустить аудиокодек для Bluetooth\nВыбор"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Частота дискретизации аудио Bluetooth"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Запустить аудиокодек для Bluetooth\nВыбор: частота дискретизации"</string>
+ <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Серым окрашены неподдерживаемые функции"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Бит на выборку аудио Bluetooth"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Запустить аудиокодек для Bluetooth\nВыбор: разрядность"</string>
<string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Режим аудиоканала Bluetooth"</string>
diff --git a/packages/SettingsLib/res/values-si/strings.xml b/packages/SettingsLib/res/values-si/strings.xml
index 43a4978..d5fbb6b 100644
--- a/packages/SettingsLib/res/values-si/strings.xml
+++ b/packages/SettingsLib/res/values-si/strings.xml
@@ -233,6 +233,7 @@
<string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"බ්ලූටූත් ශ්රව්ය කෝඩෙක් ක්රියාරම්භ කරන්න\nතෝරා ගැනීම"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"බ්ලූටූත් ශ්රව්ය නියැදි අනුපාතය"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"බ්ලූටූත් ශ්රව්ය කෝඩෙක් ක්රියාරම්භ කරන්න\nතෝරා ගැනීම: නියැදි අනුපාතය"</string>
+ <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"අළු පැහැ ගැන්වී ඇත යන්නෙන් අදහස් කරන්නේ දුරකථනය හෝ හෙඩ්සෙට් එක මගින් සහාය නොදක්වන බවයි"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"නියැදියකට බ්ලූටූත් ශ්රව්ය බිටු"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"බ්ලූටූත් ශ්රව්ය කේතය ක්රියාරම්භ කරන්න\nතෝරා ගැනීම: නියැදි සඳහා බිටු"</string>
<string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"බ්ලූටූත් ශ්රව්ය නාලිකා ප්රකාරය"</string>
diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml
index 3a3958f..ba13586 100644
--- a/packages/SettingsLib/res/values-sk/strings.xml
+++ b/packages/SettingsLib/res/values-sk/strings.xml
@@ -233,6 +233,7 @@
<string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Spustiť zvukový kodek Bluetooth\nVýber"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Bluetooth Audio – vzorkovacia frekvencia"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Spustiť zvukový kodek Bluetooth\nVýber: vzorkovacia frekvencia"</string>
+ <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Sivé možnosti nie sú podporované telefónom ani náhlavnou súpravou"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Bluetooth Audio – počet bitov na vzorku"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Spustiť zvukový kodek Bluetooth\nVýber: počet bitov na vzorku"</string>
<string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Bluetooth Audio – režim kanála"</string>
diff --git a/packages/SettingsLib/res/values-sl/strings.xml b/packages/SettingsLib/res/values-sl/strings.xml
index 068f221..90d7829 100644
--- a/packages/SettingsLib/res/values-sl/strings.xml
+++ b/packages/SettingsLib/res/values-sl/strings.xml
@@ -233,6 +233,7 @@
<string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Sproži zvočni kodek za Bluetooth\nIzbor"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Hitrost vzorčenja zvoka prek Bluetootha"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Sproži zvočni kodek za Bluetooth\nIzbor: hitrost vzorčenja"</string>
+ <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Če je možnost zatemnjena, to pomeni, da je telefon ali slušalke z mikrofonom ne podpirajo"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Bitov na vzorec za zvok prek Bluetootha"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Sproži zvočni kodek za Bluetooth\nIzbor: število bitov na vzorec"</string>
<string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Način zvočnega kanala prek Bluetootha"</string>
diff --git a/packages/SettingsLib/res/values-sq/strings.xml b/packages/SettingsLib/res/values-sq/strings.xml
index 54d4637..15b2ed3 100644
--- a/packages/SettingsLib/res/values-sq/strings.xml
+++ b/packages/SettingsLib/res/values-sq/strings.xml
@@ -233,6 +233,7 @@
<string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Aktivizo kodekun e audios me Bluetooth\nZgjedhja"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Shpejtësia e shembullit të Bluetooth Audio"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Aktivizo kodekun e audios me Bluetooth\nZgjedhja: Shpejtësia e shembullit"</string>
+ <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Çaktivizimi do të thotë se nuk mbështetet nga telefoni ose kufjet"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Bite për shembull Bluetooth Audio"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Aktivizo kodekun e audios me Bluetooth\nZgjedhja: Bite për shembull"</string>
<string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Regjimi i kanalit Bluetooth Audio"</string>
diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml
index ab081ae..381edef 100644
--- a/packages/SettingsLib/res/values-sr/strings.xml
+++ b/packages/SettingsLib/res/values-sr/strings.xml
@@ -233,6 +233,7 @@
<string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Изаберите Bluetooth аудио кодек\n"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Брзина узорковања за Bluetooth аудио"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Изаберите Bluetooth аудио кодек:\n брзина узорковања"</string>
+ <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Ако је нека ставка засивљена, то значи да је телефон или слушалице не подржавају"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Битова по узорку за Bluetooth аудио"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Изаберите Bluetooth аудио кодек:\n број битова по узорку"</string>
<string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Режим канала за Bluetooth аудио"</string>
diff --git a/packages/SettingsLib/res/values-sv/strings.xml b/packages/SettingsLib/res/values-sv/strings.xml
index cab971f..65fbe20 100644
--- a/packages/SettingsLib/res/values-sv/strings.xml
+++ b/packages/SettingsLib/res/values-sv/strings.xml
@@ -233,6 +233,7 @@
<string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Aktivera ljudkodek för Bluetooth\nVal"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Samplingsfrekvens för Bluetooth-ljud"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Aktivera ljudkodek för Bluetooth\nVal: samplingsfrekvens"</string>
+ <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"En nedtonad kodek stöds inte av telefonen eller headsetet"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Antar bitar per sampling för Bluetooth-ljud"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Aktivera ljudkodek för Bluetooth\nVal: bitar per sampling"</string>
<string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Kanalläge för Bluetooth-ljud"</string>
diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml
index df71b82..e6ccc65 100644
--- a/packages/SettingsLib/res/values-sw/strings.xml
+++ b/packages/SettingsLib/res/values-sw/strings.xml
@@ -233,6 +233,7 @@
<string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Weka Kodeki ya Sauti ya Bluetooth\nUteuzi"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Kiwango cha Sampuli ya Sauti ya Bluetooth"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Weka Kodeki ya Sauti ya Bluetooth\nUteuzi: Kasi ya Sampuli"</string>
+ <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Kipengele cha Haiwezi kutumiwa kina maana kuwa hakitumiki kwenye simu au vifaa vya sauti"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Biti za Sauti ya Bluetooth kwa Kila Sampuli"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Weka Kodeki ya Sauti ya Bluetooth\nUteuzi: Biti Kwa Kila Sampuli"</string>
<string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Hali ya Mkondo wa Sauti ya Bluetooth"</string>
diff --git a/packages/SettingsLib/res/values-ta/strings.xml b/packages/SettingsLib/res/values-ta/strings.xml
index 084ec16..f0f4bef 100644
--- a/packages/SettingsLib/res/values-ta/strings.xml
+++ b/packages/SettingsLib/res/values-ta/strings.xml
@@ -233,6 +233,7 @@
<string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"புளூடூத் ஆடியோ கோடெக்கைத் தொடங்கு\nதேர்வு"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"புளூடூத் ஆடியோ சாம்பிள் ரேட்"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"புளூடூத் ஆடியோ கோடெக்கைத் தொடங்கு\nதேர்வு: சாம்பிள் ரேட்"</string>
+ <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"கிரே-அவுட் என்றால் மொபைலாலோ ஹெட்செட்டாலோ ஆதரிக்கப்படவில்லை என்று அர்த்தம்"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"புளூடூத் ஆடியோ பிட்கள்/சாம்பிள்"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"புளூடூத் ஆடியோ கோடெக்கைத் தொடங்கு\nதேர்வு: பிட்கள் / சாம்பிள்"</string>
<string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"புளூடூத் ஆடியோ சேனல் பயன்முறை"</string>
diff --git a/packages/SettingsLib/res/values-te/strings.xml b/packages/SettingsLib/res/values-te/strings.xml
index cbcaf1a..cf5097e 100644
--- a/packages/SettingsLib/res/values-te/strings.xml
+++ b/packages/SettingsLib/res/values-te/strings.xml
@@ -233,6 +233,7 @@
<string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"బ్లూటూత్ ఆడియో కోడెక్ని సక్రియం చేయండి\nఎంపిక"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"బ్లూటూత్ ఆడియో నమూనా రేట్"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"బ్లూటూత్ ఆడియో కోడెక్ని సక్రియం చేయండి\nఎంపిక: నమూనా రేట్"</string>
+ <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"గ్రే-అవుట్ అంటే ఫోన్ లేదా హెడ్సెట్ మద్దతు లేదు అని అర్ధం"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"ఒక్కో నమూనాకు బ్లూటూత్ ఆడియో బిట్లు"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"బ్లూటూత్ ఆడియో కోడెక్ని సక్రియం చేయండి\nఎంపిక: ఒక్కో నమూనాలో బిట్లు"</string>
<string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"బ్లూటూత్ ఆడియో ఛానెల్ మోడ్"</string>
diff --git a/packages/SettingsLib/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml
index fa8caa1..145e161 100644
--- a/packages/SettingsLib/res/values-th/strings.xml
+++ b/packages/SettingsLib/res/values-th/strings.xml
@@ -233,6 +233,7 @@
<string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"ทริกเกอร์การเลือกตัวแปลงรหัส\nเสียงบลูทูธ"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"อัตราตัวอย่างเสียงบลูทูธ"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"ทริกเกอร์การเลือกตัวแปลงรหัส\nเสียงบลูทูธ: อัตราตัวอย่าง"</string>
+ <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"เป็นสีเทาหมายความว่าโทรศัพท์หรือชุดหูฟังไม่รองรับ"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"บิตต่อตัวอย่างของเสียงบลูทูธ"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"ทริกเกอร์การเลือกตัวแปลงรหัส\nเสียงบลูทูธ: บิตต่อตัวอย่าง"</string>
<string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"โหมดช่องสัญญาณเสียงบลูทูธ"</string>
diff --git a/packages/SettingsLib/res/values-tl/strings.xml b/packages/SettingsLib/res/values-tl/strings.xml
index 21fe58c..e190773 100644
--- a/packages/SettingsLib/res/values-tl/strings.xml
+++ b/packages/SettingsLib/res/values-tl/strings.xml
@@ -233,6 +233,7 @@
<string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"I-trigger ang Pagpili sa Audio Codec ng\nBluetooth"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Sample na Rate ng Bluetooth Audio"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"I-trigger ang Pagpili sa Audio Codec ng\nBluetooth: Rate ng Sample"</string>
+ <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Ang ibig sabihin ng na-gray out ay hindi sinusuportahan ng telepono o headset"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Bits Per Sample ng Bluetooth Audio"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"I-trigger ang Pagpili sa Audio Codec ng\nBluetooth: Bits Per Sample"</string>
<string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Channel Mode ng Bluetooth Audio"</string>
diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml
index 4e7f38d..dc11e80 100644
--- a/packages/SettingsLib/res/values-tr/strings.xml
+++ b/packages/SettingsLib/res/values-tr/strings.xml
@@ -233,6 +233,7 @@
<string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Bluetooth Ses Codec\'i Tetikleme\nSeçimi"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Bluetooth Ses Örnek Hızı"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Bluetooth Ses Codec\'i Tetikleme\nSeçimi: Örnek Hızı"</string>
+ <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Devre dışı bırakılmış olması telefon veya mikrofonlu kulaklık tarafından desteklenmediği anlamına gelir."</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Bluetooth Ses Örnek Başına Bit Sayısı"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Bluetooth Ses Codec\'i Tetikleme\nSeçimi: Örnek Başına Bit Sayısı"</string>
<string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Bluetooth Ses Kanalı Modu"</string>
diff --git a/packages/SettingsLib/res/values-uk/strings.xml b/packages/SettingsLib/res/values-uk/strings.xml
index 9807417..f8a88b83 100644
--- a/packages/SettingsLib/res/values-uk/strings.xml
+++ b/packages/SettingsLib/res/values-uk/strings.xml
@@ -233,6 +233,7 @@
<string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Активувати кодек для аудіо Bluetooth\nВибір"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Частота вибірки для аудіо Bluetooth"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Активувати кодек для аудіо Bluetooth\nВибір: частота зразка"</string>
+ <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Затіненння означає, що телефон або гарнітура не підтримуються"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Кількість бітів на зразок для аудіо Bluetooth"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Активувати кодек для аудіо Bluetooth\nВибір: біти на зразок"</string>
<string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Режим каналу для аудіо Bluetooth"</string>
diff --git a/packages/SettingsLib/res/values-ur/strings.xml b/packages/SettingsLib/res/values-ur/strings.xml
index e17b0b0..246b6a2 100644
--- a/packages/SettingsLib/res/values-ur/strings.xml
+++ b/packages/SettingsLib/res/values-ur/strings.xml
@@ -233,6 +233,7 @@
<string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"بلوٹوتھ آڈیو کوڈیک کو ٹریگر کریں\nانتخاب"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"بلوٹوتھ آڈیو کے نمونے کی شرح"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"بلوٹوتھ آڈیو کوڈیک کو ٹریگر کریں\nانتخاب: نمونے کی شرح"</string>
+ <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"گرے آؤٹ کا مطلب ہے فون یا ہیڈ سیٹ کے ذریعہ تعاون یافتہ نہیں"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"بلوٹوتھ آڈیو بٹس فی نمونہ"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"بلوٹوتھ آڈیو کوڈیک کو ٹریگر کریں\nانتخاب: بِٹس فی نمونہ"</string>
<string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"بلوٹوتھ آڈیو چینل موڈ"</string>
diff --git a/packages/SettingsLib/res/values-uz/strings.xml b/packages/SettingsLib/res/values-uz/strings.xml
index ea51eba..87cc2a0 100644
--- a/packages/SettingsLib/res/values-uz/strings.xml
+++ b/packages/SettingsLib/res/values-uz/strings.xml
@@ -233,6 +233,7 @@
<string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Bluetooth orqali uzatish uchun audiokodek\nTanlash"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Bluetooth audio namunasi chastotasi"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Bluetooth orqali uzatish uchun audiokodek\nTanlash: namuna chastotasi"</string>
+ <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Parametr yoqilmasa, garnitura yoki telefonda ishlamaydi"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Bluetooth audio namunasidagi bitlar soni"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Bluetooth orqali uzatish uchun audiokodek\nTanlash: namunadagi bitlar soni"</string>
<string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Bluetooth audio kanali rejimi"</string>
diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml
index 0b71a8c..0a9726a 100644
--- a/packages/SettingsLib/res/values-vi/strings.xml
+++ b/packages/SettingsLib/res/values-vi/strings.xml
@@ -233,6 +233,7 @@
<string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Kích hoạt chế độ chọn codec\nâm thanh Bluetooth"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Tốc độ lấy mẫu âm thanh Bluetooth"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Kích hoạt chế độ chọn codec\nâm thanh Bluetooth: Tần số lấy mẫu"</string>
+ <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Trạng thái chuyển sang màu xám có nghĩa là điện thoại hoặc tai nghe không hỗ trợ"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Số bit âm thanh Bluetooth mỗi mẫu"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Kích hoạt chế độ chọn codec\nâm thanh Bluetooth: Số bit trên mỗi mẫu"</string>
<string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Chế độ kênh âm thanh Bluetooth"</string>
diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml
index 1805694..514e677 100644
--- a/packages/SettingsLib/res/values-zh-rCN/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml
@@ -233,6 +233,7 @@
<string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"触发蓝牙音频编解码器\n选择"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"蓝牙音频采样率"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"触发蓝牙音频编解码器\n选择:采样率"</string>
+ <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"灰显意味着手机或耳机不支持该功能"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"蓝牙音频每样本位数"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"触发蓝牙音频编解码器\n选择:每样本位数"</string>
<string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"蓝牙音频声道模式"</string>
diff --git a/packages/SettingsLib/res/values-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml
index 1d217b5..261e8d02 100644
--- a/packages/SettingsLib/res/values-zh-rHK/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rHK/strings.xml
@@ -233,6 +233,7 @@
<string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"觸發藍牙音訊編解碼器\n選項"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"藍牙音訊取樣率"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"觸發藍牙音訊編解碼器\n選項:取樣率"</string>
+ <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"以灰色顯示代表手機或耳機不支援此音訊編解碼器"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"藍牙音訊每個樣本位元數"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"觸發藍牙音訊編解碼器\n選項:每個樣本位元數"</string>
<string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"藍牙音訊聲道模式"</string>
diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml
index ee68665..d0ba3d0 100644
--- a/packages/SettingsLib/res/values-zh-rTW/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml
@@ -233,6 +233,7 @@
<string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"觸發藍牙音訊轉碼器\n選項"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"藍牙音訊取樣率"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"觸發藍牙音訊轉碼器\n選項:取樣率"</string>
+ <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"如果顯示為灰色,表示手機或耳機不支援這項功能"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"藍牙音訊每單位樣本位元數"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"觸發藍牙音訊轉碼器\n選項:每單位樣本位元數"</string>
<string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"藍牙音訊聲道模式"</string>
diff --git a/packages/SettingsLib/res/values-zu/strings.xml b/packages/SettingsLib/res/values-zu/strings.xml
index 820aa77..f8cc50b 100644
--- a/packages/SettingsLib/res/values-zu/strings.xml
+++ b/packages/SettingsLib/res/values-zu/strings.xml
@@ -233,6 +233,7 @@
<string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Qalisa i-codec ye-bluetooth yomsindo\nUkukhethwa"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Isilinganiso sesampula yomsindo we-Bluetooth"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Qalisa i-codec ye-bluetooth yomsindo\nUkukhethwa: Isampuli yesilinganiso"</string>
+ <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Okwenziwa mpunga ngokuphelele kusho ukuthi akusekelwe ifoni noma ihedisethi"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Ama-Bits omsindo we-Bluetooth ngesampula ngayinye"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Qalisa i-codec ye-bluetooth yomsindo\nUkukhethwa: Amabhithi ngesampuli ngayinye"</string>
<string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Imodi yesiteshi somsindo we-Bluetooth"</string>
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
index 0095692..833c4ac 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
@@ -241,9 +241,7 @@
public void disconnect() {
synchronized (mProfileLock) {
- for (LocalBluetoothProfile profile : mProfiles) {
- disconnect(profile);
- }
+ mLocalAdapter.disconnectAllEnabledProfiles(mDevice);
}
// Disconnect PBAP server in case its connected
// This is to ensure all the profiles are disconnected as some CK/Hs do not
diff --git a/packages/SettingsLib/src/com/android/settingslib/drawable/UserIconDrawable.java b/packages/SettingsLib/src/com/android/settingslib/drawable/UserIconDrawable.java
index 69487d5..274696b 100644
--- a/packages/SettingsLib/src/com/android/settingslib/drawable/UserIconDrawable.java
+++ b/packages/SettingsLib/src/com/android/settingslib/drawable/UserIconDrawable.java
@@ -39,7 +39,6 @@
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.UserHandle;
-import android.os.UserManager;
import com.android.settingslib.R;
@@ -177,8 +176,8 @@
boolean isManaged = context.getSystemService(DevicePolicyManager.class)
.getProfileOwnerAsUser(userId) != null;
if (isManaged) {
- badge = getDrawableForDisplayDensity(context,
- context.getSystemService(UserManager.class).getUserBadgeResId(userId));
+ badge = getDrawableForDisplayDensity(
+ context, com.android.internal.R.drawable.ic_corp_badge_case);
}
}
return setBadge(badge);
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
index d619300..d577b5a 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
@@ -748,7 +748,20 @@
|| (mConfig != null && mConfig.shared != config.shared)) {
return false;
}
- return security == getSecurity(config);
+
+ final int configSecurity = getSecurity(config);
+ final WifiManager wifiManager = getWifiManager();
+ switch (security) {
+ case SECURITY_PSK_SAE_TRANSITION:
+ return configSecurity == SECURITY_PSK
+ || (wifiManager.isWpa3SaeSupported() && configSecurity == SECURITY_SAE);
+ case SECURITY_OWE_TRANSITION:
+ return configSecurity == SECURITY_NONE
+ || (wifiManager.isEnhancedOpenSupported()
+ && configSecurity == SECURITY_OWE);
+ default:
+ return security == configSecurity;
+ }
}
public WifiConfiguration getConfig() {
@@ -1321,10 +1334,34 @@
mAccessPointListener = listener;
}
+ private static final String sPskSuffix = "," + String.valueOf(SECURITY_PSK);
+ private static final String sSaeSuffix = "," + String.valueOf(SECURITY_SAE);
+ private static final String sPskSaeSuffix = "," + String.valueOf(SECURITY_PSK_SAE_TRANSITION);
+ private static final String sOweSuffix = "," + String.valueOf(SECURITY_OWE);
+ private static final String sOpenSuffix = "," + String.valueOf(SECURITY_NONE);
+ private static final String sOweTransSuffix = "," + String.valueOf(SECURITY_OWE_TRANSITION);
+
private boolean isKeyEqual(String compareTo) {
if (mKey == null) {
return false;
}
+
+ if (compareTo.endsWith(sPskSuffix) || compareTo.endsWith(sSaeSuffix)) {
+ if (mKey.endsWith(sPskSaeSuffix)) {
+ // Special handling for PSK-SAE transition mode. If the AP has advertised both,
+ // we compare the key with both PSK and SAE for a match.
+ return TextUtils.equals(mKey.substring(0, mKey.lastIndexOf(',')),
+ compareTo.substring(0, compareTo.lastIndexOf(',')));
+ }
+ }
+ if (compareTo.endsWith(sOpenSuffix) || compareTo.endsWith(sOweSuffix)) {
+ if (mKey.endsWith(sOweTransSuffix)) {
+ // Special handling for OWE/Open networks. If AP advertises OWE in transition mode
+ // and we have an Open network saved, allow this connection to be established.
+ return TextUtils.equals(mKey.substring(0, mKey.lastIndexOf(',')),
+ compareTo.substring(0, compareTo.lastIndexOf(',')));
+ }
+ }
return mKey.equals(compareTo);
}
@@ -1661,6 +1698,8 @@
private static int getSecurity(ScanResult result) {
if (result.capabilities.contains("WEP")) {
return SECURITY_WEP;
+ } else if (result.capabilities.contains("PSK+SAE")) {
+ return SECURITY_PSK_SAE_TRANSITION;
} else if (result.capabilities.contains("SAE")) {
return SECURITY_SAE;
} else if (result.capabilities.contains("PSK")) {
@@ -1669,6 +1708,8 @@
return SECURITY_EAP_SUITE_B;
} else if (result.capabilities.contains("EAP")) {
return SECURITY_EAP;
+ } else if (result.capabilities.contains("OWE_TRANSITION")) {
+ return SECURITY_OWE_TRANSITION;
} else if (result.capabilities.contains("OWE")) {
return SECURITY_OWE;
}
@@ -1715,6 +1756,10 @@
return "SUITE_B";
} else if (security == SECURITY_OWE) {
return "OWE";
+ } else if (security == SECURITY_PSK_SAE_TRANSITION) {
+ return "PSK+SAE";
+ } else if (security == SECURITY_OWE_TRANSITION) {
+ return "OWE_TRANSITION";
}
return "NONE";
}
@@ -1892,16 +1937,4 @@
}
}
}
-
- /**
- * Lets the caller know if the network was cloned from another network
- *
- * @return true if the network is cloned
- */
- public boolean isCloned() {
- if (mConfig == null) {
- return false;
- }
- return mConfig.clonedNetworkConfigKey != null;
- }
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java
index 51e37d1..8591116 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java
@@ -142,7 +142,7 @@
private void updateRssi(int newRssi) {
rssi = newRssi;
- level = WifiManager.calculateSignalLevel(rssi, WifiManager.RSSI_LEVELS);
+ level = mWifiManager.calculateSignalLevel(rssi);
}
private void maybeRequestNetworkScore() {
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/MasterSwitchControllerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/MasterSwitchControllerTest.java
new file mode 100644
index 0000000..69d0f2e
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/MasterSwitchControllerTest.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.settingslib.drawer;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+
+@RunWith(RobolectricTestRunner.class)
+public class MasterSwitchControllerTest {
+
+ @Rule
+ public final ExpectedException thrown = ExpectedException.none();
+
+ private MasterSwitchController mController;
+
+ @Before
+ public void setUp() {
+ mController = new TestMasterSwitchController("123");
+ }
+
+ @Test
+ public void getMetaData_shouldThrowUnsupportedOperationException() {
+ thrown.expect(UnsupportedOperationException.class);
+
+ mController.getMetaData();
+ }
+
+ @Test
+ public void getBundle_shouldThrowUnsupportedOperationException() {
+ thrown.expect(UnsupportedOperationException.class);
+
+ mController.getBundle();
+ }
+
+ static class TestMasterSwitchController extends MasterSwitchController {
+
+ private String mKey;
+
+ TestMasterSwitchController(String key) {
+ mKey = key;
+ }
+
+ @Override
+ public String getSwitchKey() {
+ return mKey;
+ }
+
+ @Override
+ protected boolean isChecked() {
+ return true;
+ }
+
+ @Override
+ protected boolean onCheckedChanged(boolean checked) {
+ return true;
+ }
+
+ @Override
+ protected String getErrorMessage(boolean attemptedChecked) {
+ return null;
+ }
+ }
+}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/SwitchesProviderTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/SwitchesProviderTest.java
index 27b3697..a740e68 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/SwitchesProviderTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/SwitchesProviderTest.java
@@ -35,6 +35,7 @@
import android.content.pm.ProviderInfo;
import android.os.Bundle;
+import com.android.settingslib.drawer.MasterSwitchControllerTest.TestMasterSwitchController;
import com.android.settingslib.drawer.SwitchController.MetaData;
import org.junit.Before;
@@ -84,8 +85,8 @@
}
@Test
- public void attachInfo_NoMetaDataInController_shouldThrowIllegalArgumentException() {
- thrown.expect(IllegalArgumentException.class);
+ public void attachInfo_NoMetaDataInController_shouldThrowNullPointerException() {
+ thrown.expect(NullPointerException.class);
final TestSwitchController controller = new TestSwitchController();
controller.setKey("123");
mSwitchesProvider.addSwitchController(controller);
@@ -123,6 +124,19 @@
}
@Test
+ public void getSwitchData_shouldNotReturnMasterSwitchData() {
+ final SwitchController controller = new TestMasterSwitchController("123");
+ mSwitchesProvider.addSwitchController(controller);
+ mSwitchesProvider.attachInfo(mContext, mProviderInfo);
+
+ final Bundle switchData = mSwitchesProvider.call(METHOD_GET_SWITCH_DATA, "uri" ,
+ null /* extras*/);
+
+ final ArrayList<Bundle> dataList = switchData.getParcelableArrayList(EXTRA_SWITCH_DATA);
+ assertThat(dataList).isEmpty();
+ }
+
+ @Test
public void getSwitchData_shouldReturnDataList() {
final TestSwitchController controller = new TestSwitchController();
controller.setKey("123");
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java
index b36eb49..9b4b97e 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java
@@ -113,7 +113,7 @@
when(mPackageManager.queryIntentContentProvidersAsUser(any(Intent.class), anyInt(),
anyInt())).thenReturn(info);
- TileUtils.getTilesForAction(mContext, UserHandle.CURRENT, IA_SETTINGS_ACTION, addedCache,
+ TileUtils.loadTilesForAction(mContext, UserHandle.CURRENT, IA_SETTINGS_ACTION, addedCache,
null /* defaultCategory */, outTiles, false /* usePriority */);
assertThat(outTiles).hasSize(2);
@@ -135,7 +135,7 @@
when(mPackageManager.queryIntentContentProvidersAsUser(any(Intent.class), anyInt(),
anyInt())).thenReturn(info);
- TileUtils.getTilesForAction(mContext, UserHandle.CURRENT, IA_SETTINGS_ACTION, addedCache,
+ TileUtils.loadTilesForAction(mContext, UserHandle.CURRENT, IA_SETTINGS_ACTION, addedCache,
null /* defaultCategory */, outTiles, false /* requiresSettings */);
assertThat(outTiles).hasSize(2);
@@ -156,7 +156,7 @@
when(mPackageManager.queryIntentContentProvidersAsUser(any(Intent.class), anyInt(),
anyInt())).thenReturn(info);
- TileUtils.getTilesForAction(mContext, UserHandle.CURRENT, IA_SETTINGS_ACTION,
+ TileUtils.loadTilesForAction(mContext, UserHandle.CURRENT, IA_SETTINGS_ACTION,
addedCache, null /* defaultCategory */, outTiles, false /* requiresSettings */);
assertThat(outTiles).isEmpty();
@@ -197,7 +197,7 @@
when(mPackageManager.queryIntentContentProvidersAsUser(any(Intent.class), anyInt(),
anyInt())).thenReturn(info);
- TileUtils.getTilesForAction(mContext, UserHandle.CURRENT, IA_SETTINGS_ACTION, addedCache,
+ TileUtils.loadTilesForAction(mContext, UserHandle.CURRENT, IA_SETTINGS_ACTION, addedCache,
null /* defaultCategory */, outTiles, false /* usePriority */);
assertThat(outTiles).hasSize(2);
@@ -222,7 +222,7 @@
when(mResources.getString(eq(123)))
.thenReturn("my localized title");
- TileUtils.getTilesForAction(mContext, UserHandle.CURRENT, IA_SETTINGS_ACTION, addedCache,
+ TileUtils.loadTilesForAction(mContext, UserHandle.CURRENT, IA_SETTINGS_ACTION, addedCache,
null /* defaultCategory */, outTiles, false /* usePriority */);
assertThat(outTiles).hasSize(2);
assertThat(outTiles.get(0).getTitle(mContext)).isEqualTo("my localized title");
@@ -245,7 +245,7 @@
when(mPackageManager.queryIntentContentProvidersAsUser(any(Intent.class), anyInt(),
anyInt())).thenReturn(info);
- TileUtils.getTilesForAction(mContext, UserHandle.CURRENT, IA_SETTINGS_ACTION, addedCache,
+ TileUtils.loadTilesForAction(mContext, UserHandle.CURRENT, IA_SETTINGS_ACTION, addedCache,
null /* defaultCategory */, outTiles, false /* usePriority */);
assertThat(outTiles.get(0).isIconTintable(mContext)).isFalse();
@@ -266,7 +266,7 @@
when(mPackageManager.queryIntentActivitiesAsUser(any(Intent.class), anyInt(), anyInt()))
.thenReturn(info);
- TileUtils.getTilesForAction(mContext, UserHandle.CURRENT, IA_SETTINGS_ACTION, addedCache,
+ TileUtils.loadTilesForAction(mContext, UserHandle.CURRENT, IA_SETTINGS_ACTION, addedCache,
null /* defaultCategory */, outTiles, false /* usePriority */);
assertThat(outTiles).hasSize(1);
@@ -276,7 +276,7 @@
resolveInfo.activityInfo.metaData.putInt(META_DATA_PREFERENCE_ICON,
com.android.internal.R.drawable.ic_phone);
outTiles.clear();
- TileUtils.getTilesForAction(mContext, UserHandle.CURRENT, IA_SETTINGS_ACTION, addedCache,
+ TileUtils.loadTilesForAction(mContext, UserHandle.CURRENT, IA_SETTINGS_ACTION, addedCache,
null /* defaultCategory */, outTiles, false /* usePriority */);
assertThat(outTiles).hasSize(1);
@@ -300,7 +300,7 @@
when(mPackageManager.queryIntentContentProvidersAsUser(any(Intent.class), anyInt(),
anyInt())).thenReturn(info);
- TileUtils.getTilesForAction(mContext, UserHandle.CURRENT, IA_SETTINGS_ACTION, addedCache,
+ TileUtils.loadTilesForAction(mContext, UserHandle.CURRENT, IA_SETTINGS_ACTION, addedCache,
null /* defaultCategory */, outTiles, false /* usePriority */);
assertThat(outTiles.get(0).isIconTintable(mContext)).isTrue();
@@ -321,7 +321,7 @@
when(mPackageManager.queryIntentContentProvidersAsUser(any(Intent.class), anyInt(),
anyInt())).thenReturn(info);
- TileUtils.getTilesForAction(mContext, UserHandle.CURRENT, IA_SETTINGS_ACTION, addedCache,
+ TileUtils.loadTilesForAction(mContext, UserHandle.CURRENT, IA_SETTINGS_ACTION, addedCache,
null /* defaultCategory */, outTiles, false /* usePriority */);
assertThat(outTiles).hasSize(2);
diff --git a/packages/SettingsProvider/Android.bp b/packages/SettingsProvider/Android.bp
index 681b494..f40d3a1 100644
--- a/packages/SettingsProvider/Android.bp
+++ b/packages/SettingsProvider/Android.bp
@@ -29,6 +29,7 @@
"src/com/android/providers/settings/SettingsBackupAgent.java",
"src/com/android/providers/settings/SettingsState.java",
"src/com/android/providers/settings/SettingsHelper.java",
+ "src/com/android/providers/settings/WifiSoftApBandChangedNotifier.java",
],
static_libs: [
"androidx.test.rules",
diff --git a/packages/SettingsProvider/res/drawable/ic_wifi_settings.xml b/packages/SettingsProvider/res/drawable/ic_wifi_settings.xml
new file mode 100644
index 0000000..cb42656
--- /dev/null
+++ b/packages/SettingsProvider/res/drawable/ic_wifi_settings.xml
@@ -0,0 +1,41 @@
+<?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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+
+ <path
+ android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" />
+ <path
+ android:fillColor="#000000"
+ android:pathData="M12.584,15.93c0.026-0.194,0.044-0.397,0.044-0.608c0-0.211-0.018-0.405-0.044-0.608l1.304-1.022
+c0.115-0.088,0.15-0.256,0.071-0.397l-1.234-2.133c-0.071-0.132-0.238-0.185-0.379-0.132l-1.533,0.617
+c-0.317-0.247-0.67-0.449-1.04-0.608L9.535,9.4c-0.018-0.132-0.141-0.247-0.3-0.247H6.768c-0.15,0-0.282,0.115-0.3,0.256
+L6.23,11.048c-0.379,0.159-0.723,0.361-1.04,0.608l-1.533-0.617c-0.141-0.053-0.3,0-0.379,0.132l-1.234,2.133
+c-0.079,0.132-0.044,0.3,0.07,0.397l1.304,1.022c-0.026,0.194-0.044,0.405-0.044,0.608s0.018,0.405,0.044,0.608l-1.304,1.022
+c-0.115,0.088-0.15,0.256-0.07,0.397l1.234,2.133c0.07,0.132,0.238,0.185,0.379,0.132l1.533-0.617
+c0.317,0.247,0.67,0.449,1.04,0.608l0.238,1.639c0.018,0.15,0.15,0.256,0.3,0.256h2.467c0.159,0,0.282-0.115,0.3-0.256
+l0.238-1.639c0.379-0.15,0.723-0.361,1.04-0.608l1.533,0.617c0.141,0.053,0.3,0,0.379-0.132l1.234-2.133
+c0.071-0.132,0.044-0.3-0.07-0.397L12.584,15.93z
+M8.002,17.481c-1.19,0-2.159-0.969-2.159-2.159s0.969-2.159,2.159-2.159
+s2.159,0.969,2.159,2.159C10.161,16.512,9.191,17.481,8.002,17.481z" />
+ <path
+ android:fillColor="#000000"
+ android:pathData="M16.003,12.026l5.995-7.474c-0.229-0.172-2.537-2.06-6-2.06s-5.771,1.889-6,2.06l5.995,7.469l0.005,0.01L16.003,12.026z" />
+</vector>
diff --git a/packages/SettingsProvider/res/values-af/strings.xml b/packages/SettingsProvider/res/values-af/strings.xml
index 79a7f2d..2c45484 100644
--- a/packages/SettingsProvider/res/values-af/strings.xml
+++ b/packages/SettingsProvider/res/values-af/strings.xml
@@ -20,4 +20,10 @@
<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="4567566098528588863">"Instellingsberging"</string>
+ <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+ <skip />
</resources>
diff --git a/packages/SettingsProvider/res/values-am/strings.xml b/packages/SettingsProvider/res/values-am/strings.xml
index 6380b99..0630560 100644
--- a/packages/SettingsProvider/res/values-am/strings.xml
+++ b/packages/SettingsProvider/res/values-am/strings.xml
@@ -20,4 +20,10 @@
<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="4567566098528588863">"የቅንብሮች ማከማቻ"</string>
+ <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+ <skip />
</resources>
diff --git a/packages/SettingsProvider/res/values-ar/strings.xml b/packages/SettingsProvider/res/values-ar/strings.xml
index ab1b808..19306a6 100644
--- a/packages/SettingsProvider/res/values-ar/strings.xml
+++ b/packages/SettingsProvider/res/values-ar/strings.xml
@@ -20,4 +20,10 @@
<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="4567566098528588863">"تخزين الإعدادات"</string>
+ <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+ <skip />
</resources>
diff --git a/packages/SettingsProvider/res/values-as/strings.xml b/packages/SettingsProvider/res/values-as/strings.xml
index 233253e..13b90d6 100644
--- a/packages/SettingsProvider/res/values-as/strings.xml
+++ b/packages/SettingsProvider/res/values-as/strings.xml
@@ -20,4 +20,10 @@
<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="4567566098528588863">"ছেটিংছসমূহৰ সঞ্চয়াগাৰ"</string>
+ <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+ <skip />
</resources>
diff --git a/packages/SettingsProvider/res/values-az/strings.xml b/packages/SettingsProvider/res/values-az/strings.xml
index e99e99b..4737a1e 100644
--- a/packages/SettingsProvider/res/values-az/strings.xml
+++ b/packages/SettingsProvider/res/values-az/strings.xml
@@ -20,4 +20,10 @@
<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="4567566098528588863">"Ayarlar Deposu"</string>
+ <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+ <skip />
</resources>
diff --git a/packages/SettingsProvider/res/values-b+sr+Latn/strings.xml b/packages/SettingsProvider/res/values-b+sr+Latn/strings.xml
index 337b18e..032dbc5 100644
--- a/packages/SettingsProvider/res/values-b+sr+Latn/strings.xml
+++ b/packages/SettingsProvider/res/values-b+sr+Latn/strings.xml
@@ -20,4 +20,10 @@
<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="4567566098528588863">"Podešavanja skladišta"</string>
+ <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+ <skip />
</resources>
diff --git a/packages/SettingsProvider/res/values-be/strings.xml b/packages/SettingsProvider/res/values-be/strings.xml
index 3a8557c..60bdb2d 100644
--- a/packages/SettingsProvider/res/values-be/strings.xml
+++ b/packages/SettingsProvider/res/values-be/strings.xml
@@ -20,4 +20,10 @@
<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="4567566098528588863">"Сховішча налад"</string>
+ <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+ <skip />
</resources>
diff --git a/packages/SettingsProvider/res/values-bg/strings.xml b/packages/SettingsProvider/res/values-bg/strings.xml
index f3d21d8..c3a994b 100644
--- a/packages/SettingsProvider/res/values-bg/strings.xml
+++ b/packages/SettingsProvider/res/values-bg/strings.xml
@@ -20,4 +20,10 @@
<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="4567566098528588863">"Настройки за хранилище"</string>
+ <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+ <skip />
</resources>
diff --git a/packages/SettingsProvider/res/values-bn/strings.xml b/packages/SettingsProvider/res/values-bn/strings.xml
index 7e72dfb..71ee99b 100644
--- a/packages/SettingsProvider/res/values-bn/strings.xml
+++ b/packages/SettingsProvider/res/values-bn/strings.xml
@@ -20,4 +20,10 @@
<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="4567566098528588863">"সেটিংস স্টোরেজ"</string>
+ <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+ <skip />
</resources>
diff --git a/packages/SettingsProvider/res/values-bs/strings.xml b/packages/SettingsProvider/res/values-bs/strings.xml
index 464a29f..09d4c68 100644
--- a/packages/SettingsProvider/res/values-bs/strings.xml
+++ b/packages/SettingsProvider/res/values-bs/strings.xml
@@ -20,4 +20,10 @@
<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="4567566098528588863">"Postavke za pohranu podataka"</string>
+ <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+ <skip />
</resources>
diff --git a/packages/SettingsProvider/res/values-ca/strings.xml b/packages/SettingsProvider/res/values-ca/strings.xml
index 9d6ac7a..ee6b51e 100644
--- a/packages/SettingsProvider/res/values-ca/strings.xml
+++ b/packages/SettingsProvider/res/values-ca/strings.xml
@@ -20,4 +20,10 @@
<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="4567566098528588863">"Configuració de l\'emmagatzematge"</string>
+ <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+ <skip />
</resources>
diff --git a/packages/SettingsProvider/res/values-cs/strings.xml b/packages/SettingsProvider/res/values-cs/strings.xml
index a28ffa1..f134e05 100644
--- a/packages/SettingsProvider/res/values-cs/strings.xml
+++ b/packages/SettingsProvider/res/values-cs/strings.xml
@@ -20,4 +20,10 @@
<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="4567566098528588863">"Paměť pro nastavení"</string>
+ <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+ <skip />
</resources>
diff --git a/packages/SettingsProvider/res/values-da/strings.xml b/packages/SettingsProvider/res/values-da/strings.xml
index ed450d5..99988a5 100644
--- a/packages/SettingsProvider/res/values-da/strings.xml
+++ b/packages/SettingsProvider/res/values-da/strings.xml
@@ -20,4 +20,10 @@
<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="4567566098528588863">"Lagring af indstillinger"</string>
+ <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+ <skip />
</resources>
diff --git a/packages/SettingsProvider/res/values-de/strings.xml b/packages/SettingsProvider/res/values-de/strings.xml
index 6effbae..ddcabaa 100644
--- a/packages/SettingsProvider/res/values-de/strings.xml
+++ b/packages/SettingsProvider/res/values-de/strings.xml
@@ -20,4 +20,10 @@
<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="4567566098528588863">"Einstellungsspeicher"</string>
+ <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+ <skip />
</resources>
diff --git a/packages/SettingsProvider/res/values-el/strings.xml b/packages/SettingsProvider/res/values-el/strings.xml
index 5bd1fa6..924fab5 100644
--- a/packages/SettingsProvider/res/values-el/strings.xml
+++ b/packages/SettingsProvider/res/values-el/strings.xml
@@ -20,4 +20,10 @@
<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="4567566098528588863">"Αποθηκευτικός χώρος ρυθμίσεων"</string>
+ <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+ <skip />
</resources>
diff --git a/packages/SettingsProvider/res/values-en-rAU/strings.xml b/packages/SettingsProvider/res/values-en-rAU/strings.xml
index c19fdd7..05cd54e 100644
--- a/packages/SettingsProvider/res/values-en-rAU/strings.xml
+++ b/packages/SettingsProvider/res/values-en-rAU/strings.xml
@@ -20,4 +20,10 @@
<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="4567566098528588863">"Settings Storage"</string>
+ <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+ <skip />
</resources>
diff --git a/packages/SettingsProvider/res/values-en-rCA/strings.xml b/packages/SettingsProvider/res/values-en-rCA/strings.xml
index c19fdd7..05cd54e 100644
--- a/packages/SettingsProvider/res/values-en-rCA/strings.xml
+++ b/packages/SettingsProvider/res/values-en-rCA/strings.xml
@@ -20,4 +20,10 @@
<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="4567566098528588863">"Settings Storage"</string>
+ <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+ <skip />
</resources>
diff --git a/packages/SettingsProvider/res/values-en-rGB/strings.xml b/packages/SettingsProvider/res/values-en-rGB/strings.xml
index c19fdd7..05cd54e 100644
--- a/packages/SettingsProvider/res/values-en-rGB/strings.xml
+++ b/packages/SettingsProvider/res/values-en-rGB/strings.xml
@@ -20,4 +20,10 @@
<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="4567566098528588863">"Settings Storage"</string>
+ <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+ <skip />
</resources>
diff --git a/packages/SettingsProvider/res/values-en-rIN/strings.xml b/packages/SettingsProvider/res/values-en-rIN/strings.xml
index c19fdd7..05cd54e 100644
--- a/packages/SettingsProvider/res/values-en-rIN/strings.xml
+++ b/packages/SettingsProvider/res/values-en-rIN/strings.xml
@@ -20,4 +20,10 @@
<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="4567566098528588863">"Settings Storage"</string>
+ <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+ <skip />
</resources>
diff --git a/packages/SettingsProvider/res/values-en-rXC/strings.xml b/packages/SettingsProvider/res/values-en-rXC/strings.xml
index 9b18e2b..fbc348b 100644
--- a/packages/SettingsProvider/res/values-en-rXC/strings.xml
+++ b/packages/SettingsProvider/res/values-en-rXC/strings.xml
@@ -20,4 +20,7 @@
<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="4567566098528588863">"Settings Storage"</string>
+ <string name="wifi_softap_config_change" msgid="5338670993556993667">"Changes to your hotspot settings"</string>
+ <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"Your hotspot band has changed."</string>
+ <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"This device doesn’t support your preference for 5GHz only. Instead, this device will use the 5GHz band when available."</string>
</resources>
diff --git a/packages/SettingsProvider/res/values-es-rUS/strings.xml b/packages/SettingsProvider/res/values-es-rUS/strings.xml
index 7a15d8b..d5e6da9 100644
--- a/packages/SettingsProvider/res/values-es-rUS/strings.xml
+++ b/packages/SettingsProvider/res/values-es-rUS/strings.xml
@@ -20,4 +20,10 @@
<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="4567566098528588863">"Almacenamiento de configuración"</string>
+ <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+ <skip />
</resources>
diff --git a/packages/SettingsProvider/res/values-es/strings.xml b/packages/SettingsProvider/res/values-es/strings.xml
index 7a15d8b..d5e6da9 100644
--- a/packages/SettingsProvider/res/values-es/strings.xml
+++ b/packages/SettingsProvider/res/values-es/strings.xml
@@ -20,4 +20,10 @@
<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="4567566098528588863">"Almacenamiento de configuración"</string>
+ <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+ <skip />
</resources>
diff --git a/packages/SettingsProvider/res/values-et/strings.xml b/packages/SettingsProvider/res/values-et/strings.xml
index 30b7293..a3e4db6 100644
--- a/packages/SettingsProvider/res/values-et/strings.xml
+++ b/packages/SettingsProvider/res/values-et/strings.xml
@@ -20,4 +20,10 @@
<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="4567566098528588863">"Seadete talletusruum"</string>
+ <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+ <skip />
</resources>
diff --git a/packages/SettingsProvider/res/values-eu/strings.xml b/packages/SettingsProvider/res/values-eu/strings.xml
index 6780ae0..8d410de1 100644
--- a/packages/SettingsProvider/res/values-eu/strings.xml
+++ b/packages/SettingsProvider/res/values-eu/strings.xml
@@ -20,4 +20,10 @@
<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="4567566098528588863">"Ezarpenen biltegia"</string>
+ <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+ <skip />
</resources>
diff --git a/packages/SettingsProvider/res/values-fa/strings.xml b/packages/SettingsProvider/res/values-fa/strings.xml
index 97fe0ab..ed9d168 100644
--- a/packages/SettingsProvider/res/values-fa/strings.xml
+++ b/packages/SettingsProvider/res/values-fa/strings.xml
@@ -20,4 +20,10 @@
<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="4567566098528588863">"تنظیم محل ذخیره"</string>
+ <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+ <skip />
</resources>
diff --git a/packages/SettingsProvider/res/values-fi/strings.xml b/packages/SettingsProvider/res/values-fi/strings.xml
index 83c7f66..9ff2c41 100644
--- a/packages/SettingsProvider/res/values-fi/strings.xml
+++ b/packages/SettingsProvider/res/values-fi/strings.xml
@@ -20,4 +20,10 @@
<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="4567566098528588863">"Asetuksien tallennus"</string>
+ <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+ <skip />
</resources>
diff --git a/packages/SettingsProvider/res/values-fr-rCA/strings.xml b/packages/SettingsProvider/res/values-fr-rCA/strings.xml
index c90eb09..fdfdb1d 100644
--- a/packages/SettingsProvider/res/values-fr-rCA/strings.xml
+++ b/packages/SettingsProvider/res/values-fr-rCA/strings.xml
@@ -20,4 +20,10 @@
<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="4567566098528588863">"Stockage des paramètres"</string>
+ <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+ <skip />
</resources>
diff --git a/packages/SettingsProvider/res/values-fr/strings.xml b/packages/SettingsProvider/res/values-fr/strings.xml
index c90eb09..fdfdb1d 100644
--- a/packages/SettingsProvider/res/values-fr/strings.xml
+++ b/packages/SettingsProvider/res/values-fr/strings.xml
@@ -20,4 +20,10 @@
<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="4567566098528588863">"Stockage des paramètres"</string>
+ <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+ <skip />
</resources>
diff --git a/packages/SettingsProvider/res/values-gl/strings.xml b/packages/SettingsProvider/res/values-gl/strings.xml
index 80ef310..7b1599e 100644
--- a/packages/SettingsProvider/res/values-gl/strings.xml
+++ b/packages/SettingsProvider/res/values-gl/strings.xml
@@ -20,4 +20,10 @@
<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="4567566098528588863">"Almacenamento da configuración"</string>
+ <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+ <skip />
</resources>
diff --git a/packages/SettingsProvider/res/values-gu/strings.xml b/packages/SettingsProvider/res/values-gu/strings.xml
index 7241974..00246f9 100644
--- a/packages/SettingsProvider/res/values-gu/strings.xml
+++ b/packages/SettingsProvider/res/values-gu/strings.xml
@@ -20,4 +20,10 @@
<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="4567566098528588863">"સેટિંગ્સ સંગ્રહ"</string>
+ <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+ <skip />
</resources>
diff --git a/packages/SettingsProvider/res/values-hi/strings.xml b/packages/SettingsProvider/res/values-hi/strings.xml
index da8193f..35ed78f 100644
--- a/packages/SettingsProvider/res/values-hi/strings.xml
+++ b/packages/SettingsProvider/res/values-hi/strings.xml
@@ -20,4 +20,10 @@
<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="4567566098528588863">"सेटिंग मेमोरी"</string>
+ <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+ <skip />
</resources>
diff --git a/packages/SettingsProvider/res/values-hr/strings.xml b/packages/SettingsProvider/res/values-hr/strings.xml
index 87f1270..070d061 100644
--- a/packages/SettingsProvider/res/values-hr/strings.xml
+++ b/packages/SettingsProvider/res/values-hr/strings.xml
@@ -20,4 +20,10 @@
<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="4567566098528588863">"Postavke pohrane"</string>
+ <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+ <skip />
</resources>
diff --git a/packages/SettingsProvider/res/values-hu/strings.xml b/packages/SettingsProvider/res/values-hu/strings.xml
index dab1b17..97124ae 100644
--- a/packages/SettingsProvider/res/values-hu/strings.xml
+++ b/packages/SettingsProvider/res/values-hu/strings.xml
@@ -20,4 +20,10 @@
<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="4567566098528588863">"Beállítástároló"</string>
+ <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+ <skip />
</resources>
diff --git a/packages/SettingsProvider/res/values-hy/strings.xml b/packages/SettingsProvider/res/values-hy/strings.xml
index b1f1afb..d494012 100644
--- a/packages/SettingsProvider/res/values-hy/strings.xml
+++ b/packages/SettingsProvider/res/values-hy/strings.xml
@@ -20,4 +20,10 @@
<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="4567566098528588863">"Կարգավորումների պահուստ"</string>
+ <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+ <skip />
</resources>
diff --git a/packages/SettingsProvider/res/values-in/strings.xml b/packages/SettingsProvider/res/values-in/strings.xml
index bed20eb..4ec8f84 100644
--- a/packages/SettingsProvider/res/values-in/strings.xml
+++ b/packages/SettingsProvider/res/values-in/strings.xml
@@ -20,4 +20,10 @@
<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="4567566098528588863">"Setelan Penyimpanan"</string>
+ <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+ <skip />
</resources>
diff --git a/packages/SettingsProvider/res/values-is/strings.xml b/packages/SettingsProvider/res/values-is/strings.xml
index c4e2aa6..d75abae 100644
--- a/packages/SettingsProvider/res/values-is/strings.xml
+++ b/packages/SettingsProvider/res/values-is/strings.xml
@@ -20,4 +20,10 @@
<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="4567566098528588863">"Stillingageymsla"</string>
+ <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+ <skip />
</resources>
diff --git a/packages/SettingsProvider/res/values-it/strings.xml b/packages/SettingsProvider/res/values-it/strings.xml
index ba1431d..a1e3901 100644
--- a/packages/SettingsProvider/res/values-it/strings.xml
+++ b/packages/SettingsProvider/res/values-it/strings.xml
@@ -20,4 +20,10 @@
<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="4567566098528588863">"Memoria impostazioni"</string>
+ <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+ <skip />
</resources>
diff --git a/packages/SettingsProvider/res/values-iw/strings.xml b/packages/SettingsProvider/res/values-iw/strings.xml
index ad2eaf4..c14f776 100644
--- a/packages/SettingsProvider/res/values-iw/strings.xml
+++ b/packages/SettingsProvider/res/values-iw/strings.xml
@@ -20,4 +20,10 @@
<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="4567566098528588863">"אחסון הגדרות"</string>
+ <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+ <skip />
</resources>
diff --git a/packages/SettingsProvider/res/values-ja/strings.xml b/packages/SettingsProvider/res/values-ja/strings.xml
index d222ca9..b11ec3b 100644
--- a/packages/SettingsProvider/res/values-ja/strings.xml
+++ b/packages/SettingsProvider/res/values-ja/strings.xml
@@ -20,4 +20,10 @@
<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="4567566098528588863">"ストレージの設定"</string>
+ <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+ <skip />
</resources>
diff --git a/packages/SettingsProvider/res/values-ka/strings.xml b/packages/SettingsProvider/res/values-ka/strings.xml
index 691a2e9..d08e71e 100644
--- a/packages/SettingsProvider/res/values-ka/strings.xml
+++ b/packages/SettingsProvider/res/values-ka/strings.xml
@@ -20,4 +20,10 @@
<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="4567566098528588863">"პარამეტრების საცავი"</string>
+ <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+ <skip />
</resources>
diff --git a/packages/SettingsProvider/res/values-kk/strings.xml b/packages/SettingsProvider/res/values-kk/strings.xml
index 8cf8af2..c07264c 100644
--- a/packages/SettingsProvider/res/values-kk/strings.xml
+++ b/packages/SettingsProvider/res/values-kk/strings.xml
@@ -20,4 +20,10 @@
<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="4567566098528588863">"Параметрлер жады"</string>
+ <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+ <skip />
</resources>
diff --git a/packages/SettingsProvider/res/values-km/strings.xml b/packages/SettingsProvider/res/values-km/strings.xml
index 7be62427..c880ead 100644
--- a/packages/SettingsProvider/res/values-km/strings.xml
+++ b/packages/SettingsProvider/res/values-km/strings.xml
@@ -20,4 +20,10 @@
<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="4567566098528588863">"កំណត់ការផ្ទុក"</string>
+ <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+ <skip />
</resources>
diff --git a/packages/SettingsProvider/res/values-kn/strings.xml b/packages/SettingsProvider/res/values-kn/strings.xml
index ca427ec..d823323 100644
--- a/packages/SettingsProvider/res/values-kn/strings.xml
+++ b/packages/SettingsProvider/res/values-kn/strings.xml
@@ -20,4 +20,10 @@
<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="4567566098528588863">"ಸೆಟ್ಟಿಂಗ್ಗಳ ಸಂಗ್ರಹಣೆ"</string>
+ <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+ <skip />
</resources>
diff --git a/packages/SettingsProvider/res/values-ko/strings.xml b/packages/SettingsProvider/res/values-ko/strings.xml
index 8e0cc75..ab8fb2b 100644
--- a/packages/SettingsProvider/res/values-ko/strings.xml
+++ b/packages/SettingsProvider/res/values-ko/strings.xml
@@ -20,4 +20,10 @@
<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="4567566098528588863">"설정 저장소"</string>
+ <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+ <skip />
</resources>
diff --git a/packages/SettingsProvider/res/values-ky/strings.xml b/packages/SettingsProvider/res/values-ky/strings.xml
index 2b3cf61..566c481 100644
--- a/packages/SettingsProvider/res/values-ky/strings.xml
+++ b/packages/SettingsProvider/res/values-ky/strings.xml
@@ -20,4 +20,10 @@
<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="4567566098528588863">"Жөндөөлөрдү сактоо"</string>
+ <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+ <skip />
</resources>
diff --git a/packages/SettingsProvider/res/values-lo/strings.xml b/packages/SettingsProvider/res/values-lo/strings.xml
index 4e57936..1aa5fe9 100644
--- a/packages/SettingsProvider/res/values-lo/strings.xml
+++ b/packages/SettingsProvider/res/values-lo/strings.xml
@@ -20,4 +20,10 @@
<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="4567566098528588863">"ບ່ອນເກັບຂໍ້ມູນການຕັ້ງຄ່າ"</string>
+ <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+ <skip />
</resources>
diff --git a/packages/SettingsProvider/res/values-lt/strings.xml b/packages/SettingsProvider/res/values-lt/strings.xml
index 5b4432f..47cd6b4 100644
--- a/packages/SettingsProvider/res/values-lt/strings.xml
+++ b/packages/SettingsProvider/res/values-lt/strings.xml
@@ -20,4 +20,10 @@
<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="4567566098528588863">"Nustatymų saugykla"</string>
+ <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+ <skip />
</resources>
diff --git a/packages/SettingsProvider/res/values-lv/strings.xml b/packages/SettingsProvider/res/values-lv/strings.xml
index c83580c..d221d46 100644
--- a/packages/SettingsProvider/res/values-lv/strings.xml
+++ b/packages/SettingsProvider/res/values-lv/strings.xml
@@ -20,4 +20,10 @@
<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="4567566098528588863">"Iestatījumu krātuve"</string>
+ <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+ <skip />
</resources>
diff --git a/packages/SettingsProvider/res/values-mk/strings.xml b/packages/SettingsProvider/res/values-mk/strings.xml
index f281bae..dc74c4a 100644
--- a/packages/SettingsProvider/res/values-mk/strings.xml
+++ b/packages/SettingsProvider/res/values-mk/strings.xml
@@ -20,4 +20,10 @@
<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="4567566098528588863">"Поставки за меморија"</string>
+ <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+ <skip />
</resources>
diff --git a/packages/SettingsProvider/res/values-ml/strings.xml b/packages/SettingsProvider/res/values-ml/strings.xml
index 43a88e1..a11e236 100644
--- a/packages/SettingsProvider/res/values-ml/strings.xml
+++ b/packages/SettingsProvider/res/values-ml/strings.xml
@@ -20,4 +20,10 @@
<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="4567566098528588863">"സംഭരണ ക്രമീകരണം"</string>
+ <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+ <skip />
</resources>
diff --git a/packages/SettingsProvider/res/values-mn/strings.xml b/packages/SettingsProvider/res/values-mn/strings.xml
index 9452145..f6437c75 100644
--- a/packages/SettingsProvider/res/values-mn/strings.xml
+++ b/packages/SettingsProvider/res/values-mn/strings.xml
@@ -20,4 +20,10 @@
<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="4567566098528588863">"Тохиргооны Сан"</string>
+ <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+ <skip />
</resources>
diff --git a/packages/SettingsProvider/res/values-mr/strings.xml b/packages/SettingsProvider/res/values-mr/strings.xml
index 65a876f..7888488 100644
--- a/packages/SettingsProvider/res/values-mr/strings.xml
+++ b/packages/SettingsProvider/res/values-mr/strings.xml
@@ -20,4 +20,10 @@
<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="4567566098528588863">"सेटिंग्ज संचयन"</string>
+ <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+ <skip />
</resources>
diff --git a/packages/SettingsProvider/res/values-ms/strings.xml b/packages/SettingsProvider/res/values-ms/strings.xml
index 9108b07..bcde71c 100644
--- a/packages/SettingsProvider/res/values-ms/strings.xml
+++ b/packages/SettingsProvider/res/values-ms/strings.xml
@@ -20,4 +20,10 @@
<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="4567566098528588863">"Storan Tetapan"</string>
+ <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+ <skip />
</resources>
diff --git a/packages/SettingsProvider/res/values-my/strings.xml b/packages/SettingsProvider/res/values-my/strings.xml
index 0c5e840..b2e670e 100644
--- a/packages/SettingsProvider/res/values-my/strings.xml
+++ b/packages/SettingsProvider/res/values-my/strings.xml
@@ -20,4 +20,10 @@
<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="4567566098528588863">"သိုလှောင်မှုဆက်တင်များ"</string>
+ <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+ <skip />
</resources>
diff --git a/packages/SettingsProvider/res/values-nb/strings.xml b/packages/SettingsProvider/res/values-nb/strings.xml
index ad18f94..5c60ad7 100644
--- a/packages/SettingsProvider/res/values-nb/strings.xml
+++ b/packages/SettingsProvider/res/values-nb/strings.xml
@@ -20,4 +20,10 @@
<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="4567566098528588863">"Lagring av innstillinger"</string>
+ <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+ <skip />
</resources>
diff --git a/packages/SettingsProvider/res/values-ne/strings.xml b/packages/SettingsProvider/res/values-ne/strings.xml
index af6ef62..8c4f8c8 100644
--- a/packages/SettingsProvider/res/values-ne/strings.xml
+++ b/packages/SettingsProvider/res/values-ne/strings.xml
@@ -20,4 +20,10 @@
<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="4567566098528588863">"सेटिङहरू भण्डारण"</string>
+ <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+ <skip />
</resources>
diff --git a/packages/SettingsProvider/res/values-nl/strings.xml b/packages/SettingsProvider/res/values-nl/strings.xml
index 010fdb5..7ad4588 100644
--- a/packages/SettingsProvider/res/values-nl/strings.xml
+++ b/packages/SettingsProvider/res/values-nl/strings.xml
@@ -20,4 +20,10 @@
<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="4567566098528588863">"Opslagruimte voor instellingen"</string>
+ <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+ <skip />
</resources>
diff --git a/packages/SettingsProvider/res/values-or/strings.xml b/packages/SettingsProvider/res/values-or/strings.xml
index 04f68c8..1837219 100644
--- a/packages/SettingsProvider/res/values-or/strings.xml
+++ b/packages/SettingsProvider/res/values-or/strings.xml
@@ -20,4 +20,10 @@
<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="4567566098528588863">"ସେଟିଙ୍ଗ ଷ୍ଟୋରେଜ୍"</string>
+ <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+ <skip />
</resources>
diff --git a/packages/SettingsProvider/res/values-pa/strings.xml b/packages/SettingsProvider/res/values-pa/strings.xml
index 1813bec..2961435 100644
--- a/packages/SettingsProvider/res/values-pa/strings.xml
+++ b/packages/SettingsProvider/res/values-pa/strings.xml
@@ -20,4 +20,10 @@
<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="4567566098528588863">"ਸੈਟਿੰਗਾਂ ਸਟੋਰੇਜ"</string>
+ <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+ <skip />
</resources>
diff --git a/packages/SettingsProvider/res/values-pl/strings.xml b/packages/SettingsProvider/res/values-pl/strings.xml
index 9f81e63..9963aee 100644
--- a/packages/SettingsProvider/res/values-pl/strings.xml
+++ b/packages/SettingsProvider/res/values-pl/strings.xml
@@ -20,4 +20,10 @@
<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="4567566098528588863">"Pamięć ustawień"</string>
+ <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+ <skip />
</resources>
diff --git a/packages/SettingsProvider/res/values-pt-rBR/strings.xml b/packages/SettingsProvider/res/values-pt-rBR/strings.xml
index ade1746..e25e82e 100644
--- a/packages/SettingsProvider/res/values-pt-rBR/strings.xml
+++ b/packages/SettingsProvider/res/values-pt-rBR/strings.xml
@@ -20,4 +20,10 @@
<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="4567566098528588863">"Armazenamento de configurações"</string>
+ <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+ <skip />
</resources>
diff --git a/packages/SettingsProvider/res/values-pt-rPT/strings.xml b/packages/SettingsProvider/res/values-pt-rPT/strings.xml
index c7dc9e6..3b95a31 100644
--- a/packages/SettingsProvider/res/values-pt-rPT/strings.xml
+++ b/packages/SettingsProvider/res/values-pt-rPT/strings.xml
@@ -20,4 +20,10 @@
<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="4567566098528588863">"Armazenamento de definições"</string>
+ <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+ <skip />
</resources>
diff --git a/packages/SettingsProvider/res/values-pt/strings.xml b/packages/SettingsProvider/res/values-pt/strings.xml
index ade1746..e25e82e 100644
--- a/packages/SettingsProvider/res/values-pt/strings.xml
+++ b/packages/SettingsProvider/res/values-pt/strings.xml
@@ -20,4 +20,10 @@
<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="4567566098528588863">"Armazenamento de configurações"</string>
+ <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+ <skip />
</resources>
diff --git a/packages/SettingsProvider/res/values-ro/strings.xml b/packages/SettingsProvider/res/values-ro/strings.xml
index 53e9429..5a5ac6d 100644
--- a/packages/SettingsProvider/res/values-ro/strings.xml
+++ b/packages/SettingsProvider/res/values-ro/strings.xml
@@ -20,4 +20,10 @@
<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="4567566098528588863">"Stocare setări"</string>
+ <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+ <skip />
</resources>
diff --git a/packages/SettingsProvider/res/values-ru/strings.xml b/packages/SettingsProvider/res/values-ru/strings.xml
index 4c15984..15ca313 100644
--- a/packages/SettingsProvider/res/values-ru/strings.xml
+++ b/packages/SettingsProvider/res/values-ru/strings.xml
@@ -20,4 +20,10 @@
<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="4567566098528588863">"Хранилище настроек"</string>
+ <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+ <skip />
</resources>
diff --git a/packages/SettingsProvider/res/values-si/strings.xml b/packages/SettingsProvider/res/values-si/strings.xml
index 24ef798..feff43c 100644
--- a/packages/SettingsProvider/res/values-si/strings.xml
+++ b/packages/SettingsProvider/res/values-si/strings.xml
@@ -20,4 +20,10 @@
<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="4567566098528588863">"සැකසීම් ගබඩාව"</string>
+ <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+ <skip />
</resources>
diff --git a/packages/SettingsProvider/res/values-sk/strings.xml b/packages/SettingsProvider/res/values-sk/strings.xml
index 955c834..1207a94 100644
--- a/packages/SettingsProvider/res/values-sk/strings.xml
+++ b/packages/SettingsProvider/res/values-sk/strings.xml
@@ -20,4 +20,10 @@
<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="4567566098528588863">"Ukladací priestor nastavení"</string>
+ <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+ <skip />
</resources>
diff --git a/packages/SettingsProvider/res/values-sl/strings.xml b/packages/SettingsProvider/res/values-sl/strings.xml
index 3d7768d..28a9937 100644
--- a/packages/SettingsProvider/res/values-sl/strings.xml
+++ b/packages/SettingsProvider/res/values-sl/strings.xml
@@ -20,4 +20,10 @@
<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="4567566098528588863">"Shramba nastavitev"</string>
+ <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+ <skip />
</resources>
diff --git a/packages/SettingsProvider/res/values-sq/strings.xml b/packages/SettingsProvider/res/values-sq/strings.xml
index a8e66d5..977fe02 100644
--- a/packages/SettingsProvider/res/values-sq/strings.xml
+++ b/packages/SettingsProvider/res/values-sq/strings.xml
@@ -20,4 +20,10 @@
<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="4567566098528588863">"Hapësira ruajtëse e \"Cilësimeve\""</string>
+ <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+ <skip />
</resources>
diff --git a/packages/SettingsProvider/res/values-sr/strings.xml b/packages/SettingsProvider/res/values-sr/strings.xml
index 7082761..74b9dde 100644
--- a/packages/SettingsProvider/res/values-sr/strings.xml
+++ b/packages/SettingsProvider/res/values-sr/strings.xml
@@ -20,4 +20,10 @@
<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="4567566098528588863">"Подешавања складишта"</string>
+ <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+ <skip />
</resources>
diff --git a/packages/SettingsProvider/res/values-sv/strings.xml b/packages/SettingsProvider/res/values-sv/strings.xml
index b6de084..1444626 100644
--- a/packages/SettingsProvider/res/values-sv/strings.xml
+++ b/packages/SettingsProvider/res/values-sv/strings.xml
@@ -20,4 +20,10 @@
<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="4567566098528588863">"Lagring av inställningar"</string>
+ <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+ <skip />
</resources>
diff --git a/packages/SettingsProvider/res/values-sw/strings.xml b/packages/SettingsProvider/res/values-sw/strings.xml
index d17f60b..c244d88 100644
--- a/packages/SettingsProvider/res/values-sw/strings.xml
+++ b/packages/SettingsProvider/res/values-sw/strings.xml
@@ -20,4 +20,10 @@
<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="4567566098528588863">"Hifadhi ya Mipangilio"</string>
+ <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+ <skip />
</resources>
diff --git a/packages/SettingsProvider/res/values-ta/strings.xml b/packages/SettingsProvider/res/values-ta/strings.xml
index 7a86878..b26c875 100644
--- a/packages/SettingsProvider/res/values-ta/strings.xml
+++ b/packages/SettingsProvider/res/values-ta/strings.xml
@@ -20,4 +20,10 @@
<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="4567566098528588863">"அமைப்புகளின் சேமிப்பிடம்"</string>
+ <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+ <skip />
</resources>
diff --git a/packages/SettingsProvider/res/values-te/strings.xml b/packages/SettingsProvider/res/values-te/strings.xml
index e51ba88..2a4971a 100644
--- a/packages/SettingsProvider/res/values-te/strings.xml
+++ b/packages/SettingsProvider/res/values-te/strings.xml
@@ -20,4 +20,10 @@
<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="4567566098528588863">"సెట్టింగ్ల నిల్వ"</string>
+ <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+ <skip />
</resources>
diff --git a/packages/SettingsProvider/res/values-th/strings.xml b/packages/SettingsProvider/res/values-th/strings.xml
index ae8ba6a..db47654 100644
--- a/packages/SettingsProvider/res/values-th/strings.xml
+++ b/packages/SettingsProvider/res/values-th/strings.xml
@@ -20,4 +20,10 @@
<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="4567566098528588863">"ที่เก็บข้อมูลการตั้งค่า"</string>
+ <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+ <skip />
</resources>
diff --git a/packages/SettingsProvider/res/values-tl/strings.xml b/packages/SettingsProvider/res/values-tl/strings.xml
index 0fe535e..71c6266 100644
--- a/packages/SettingsProvider/res/values-tl/strings.xml
+++ b/packages/SettingsProvider/res/values-tl/strings.xml
@@ -20,4 +20,10 @@
<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="4567566098528588863">"Storage ng Mga Setting"</string>
+ <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+ <skip />
</resources>
diff --git a/packages/SettingsProvider/res/values-tr/strings.xml b/packages/SettingsProvider/res/values-tr/strings.xml
index e99e99b..4737a1e 100644
--- a/packages/SettingsProvider/res/values-tr/strings.xml
+++ b/packages/SettingsProvider/res/values-tr/strings.xml
@@ -20,4 +20,10 @@
<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="4567566098528588863">"Ayarlar Deposu"</string>
+ <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+ <skip />
</resources>
diff --git a/packages/SettingsProvider/res/values-uk/strings.xml b/packages/SettingsProvider/res/values-uk/strings.xml
index 900dd07..2c77c6a61 100644
--- a/packages/SettingsProvider/res/values-uk/strings.xml
+++ b/packages/SettingsProvider/res/values-uk/strings.xml
@@ -20,4 +20,10 @@
<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="4567566098528588863">"Сховище налаштувань"</string>
+ <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+ <skip />
</resources>
diff --git a/packages/SettingsProvider/res/values-ur/strings.xml b/packages/SettingsProvider/res/values-ur/strings.xml
index e79249b..31694e0 100644
--- a/packages/SettingsProvider/res/values-ur/strings.xml
+++ b/packages/SettingsProvider/res/values-ur/strings.xml
@@ -20,4 +20,10 @@
<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="4567566098528588863">"ترتیبات کا اسٹوریج"</string>
+ <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+ <skip />
</resources>
diff --git a/packages/SettingsProvider/res/values-uz/strings.xml b/packages/SettingsProvider/res/values-uz/strings.xml
index 38f0ce5..86a980e 100644
--- a/packages/SettingsProvider/res/values-uz/strings.xml
+++ b/packages/SettingsProvider/res/values-uz/strings.xml
@@ -20,4 +20,10 @@
<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="4567566098528588863">"Sozlamalar xotirasi"</string>
+ <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+ <skip />
</resources>
diff --git a/packages/SettingsProvider/res/values-vi/strings.xml b/packages/SettingsProvider/res/values-vi/strings.xml
index 015fbfd..6476927 100644
--- a/packages/SettingsProvider/res/values-vi/strings.xml
+++ b/packages/SettingsProvider/res/values-vi/strings.xml
@@ -20,4 +20,10 @@
<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="4567566098528588863">"Lưu trữ bộ nhớ"</string>
+ <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+ <skip />
</resources>
diff --git a/packages/SettingsProvider/res/values-zh-rCN/strings.xml b/packages/SettingsProvider/res/values-zh-rCN/strings.xml
index 11c5d6c..1395912 100644
--- a/packages/SettingsProvider/res/values-zh-rCN/strings.xml
+++ b/packages/SettingsProvider/res/values-zh-rCN/strings.xml
@@ -20,4 +20,10 @@
<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="4567566098528588863">"设置存储"</string>
+ <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+ <skip />
</resources>
diff --git a/packages/SettingsProvider/res/values-zh-rHK/strings.xml b/packages/SettingsProvider/res/values-zh-rHK/strings.xml
index 977c9b9..2845264 100644
--- a/packages/SettingsProvider/res/values-zh-rHK/strings.xml
+++ b/packages/SettingsProvider/res/values-zh-rHK/strings.xml
@@ -20,4 +20,10 @@
<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="4567566098528588863">"設定儲存空間"</string>
+ <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+ <skip />
</resources>
diff --git a/packages/SettingsProvider/res/values-zh-rTW/strings.xml b/packages/SettingsProvider/res/values-zh-rTW/strings.xml
index 977c9b9..2845264 100644
--- a/packages/SettingsProvider/res/values-zh-rTW/strings.xml
+++ b/packages/SettingsProvider/res/values-zh-rTW/strings.xml
@@ -20,4 +20,10 @@
<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="4567566098528588863">"設定儲存空間"</string>
+ <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+ <skip />
</resources>
diff --git a/packages/SettingsProvider/res/values-zu/strings.xml b/packages/SettingsProvider/res/values-zu/strings.xml
index cb5a781..8c1d9e0 100644
--- a/packages/SettingsProvider/res/values-zu/strings.xml
+++ b/packages/SettingsProvider/res/values-zu/strings.xml
@@ -20,4 +20,10 @@
<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="4567566098528588863">"Izilungiselelo zesitoreji"</string>
+ <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+ <skip />
</resources>
diff --git a/packages/SettingsProvider/res/values/strings.xml b/packages/SettingsProvider/res/values/strings.xml
index 9ca575e..3787727 100644
--- a/packages/SettingsProvider/res/values/strings.xml
+++ b/packages/SettingsProvider/res/values/strings.xml
@@ -19,4 +19,19 @@
<resources>
<!-- Name of the activity for Settings storage. -->
<string name="app_label">Settings Storage</string>
+
+ <!-- A notification is shown when the user's softap config has been changed due to underlying
+ hardware restrictions. This is the notifications's title.
+ [CHAR_LIMIT=NONE] -->
+ <string name="wifi_softap_config_change">Changes to your hotspot settings</string>
+
+ <!-- A notification is shown when the user's softap config has been changed due to underlying
+ hardware restrictions. This is the notification's summary message.
+ [CHAR_LIMIT=NONE] -->
+ <string name="wifi_softap_config_change_summary">Your hotspot band has changed.</string>
+
+ <!-- A notification is shown when the user's softap config has been changed due to underlying
+ hardware restrictions. This is the notification's full message.
+ [CHAR_LIMIT=NONE] -->
+ <string name="wifi_softap_config_change_detailed">This device doesn\u2019t support your preference for 5GHz only. Instead, this device will use the 5GHz band when available.</string>
</resources>
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
index 7e60452..443288c 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
@@ -895,11 +895,9 @@
// the apBand preference
boolean dualMode = mWifiManager.isDualModeSupported();
int storedApBand = mWifiManager.getWifiApConfiguration().apBand;
- if (dualMode) {
- if (storedApBand != originalApBand) {
- Log.d(TAG, "restored ap configuration requires a conversion, notify the user");
- mWifiManager.notifyUserOfApBandConversion();
- }
+ if (dualMode && storedApBand != originalApBand) {
+ Log.d(TAG, "restored ap configuration requires a conversion, notify the user");
+ WifiSoftApBandChangedNotifier.notifyUserOfApBandConversion(this);
}
} catch (IOException | BackupUtils.BadVersionException e) {
Log.e(TAG, "Failed to unMarshal SoftAPConfiguration " + e.getMessage());
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
index 55a51da..33e0fd2 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
@@ -2248,12 +2248,6 @@
SecureSettingsProto.Notification.IN_CALL_NOTIFICATION_ENABLED);
p.end(notificationToken);
- final long packageVerifierToken = p.start(SecureSettingsProto.PACKAGE_VERIFIER);
- dumpSetting(s, p,
- Settings.Secure.PACKAGE_VERIFIER_USER_CONSENT,
- SecureSettingsProto.PackageVerifier.USER_CONSENT);
- p.end(packageVerifierToken);
-
final long parentalControlToken = p.start(SecureSettingsProto.PARENTAL_CONTROL);
dumpSetting(s, p,
Settings.Secure.PARENTAL_CONTROL_ENABLED,
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index f5d1ccf..0959de9 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -101,6 +101,7 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
+import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
@@ -383,6 +384,13 @@
break;
}
+ case Settings.CALL_METHOD_SET_ALL_CONFIG: {
+ String prefix = getSettingPrefix(args);
+ Map<String, String> flags = getSettingFlags(args);
+ setAllConfigSettings(prefix, flags);
+ break;
+ }
+
case Settings.CALL_METHOD_RESET_CONFIG: {
final int mode = getResetModeEnforcingPermission(args);
String prefix = getSettingPrefix(args);
@@ -1030,6 +1038,19 @@
MUTATION_OPERATION_INSERT, 0);
}
+ private boolean setAllConfigSettings(String prefix, Map<String, String> keyValues) {
+ if (DEBUG) {
+ Slog.v(LOG_TAG, "setAllConfigSettings for prefix: " + prefix);
+ }
+
+ enforceWritePermission(Manifest.permission.WRITE_DEVICE_CONFIG);
+
+ synchronized (mLock) {
+ return mSettingsRegistry.setSettingsLocked(SETTINGS_TYPE_CONFIG, UserHandle.USER_SYSTEM,
+ prefix, keyValues, resolveCallingPackage());
+ }
+ }
+
private boolean deleteConfigSetting(String name) {
if (DEBUG) {
Slog.v(LOG_TAG, "deleteConfigSetting(" + name + ")");
@@ -2117,6 +2138,11 @@
return (args != null) ? args.getString(Settings.CALL_METHOD_PREFIX_KEY) : null;
}
+ private static Map<String, String> getSettingFlags(Bundle args) {
+ return (args != null) ? (HashMap) args.getSerializable(Settings.CALL_METHOD_FLAGS_KEY)
+ : Collections.emptyMap();
+ }
+
private static boolean getSettingMakeDefault(Bundle args) {
return (args != null) && args.getBoolean(Settings.CALL_METHOD_MAKE_DEFAULT_KEY);
}
@@ -2485,7 +2511,7 @@
final int key = makeKey(type, userId);
SettingsState settingsState = peekSettingsStateLocked(key);
if (settingsState == null) {
- return new ArrayList<String>();
+ return new ArrayList<>();
}
return settingsState.getSettingNamesLocked();
}
@@ -2645,6 +2671,22 @@
return success;
}
+ public boolean setSettingsLocked(int type, int userId, String prefix,
+ Map<String, String> keyValues, String packageName) {
+ final int key = makeKey(type, userId);
+
+ SettingsState settingsState = peekSettingsStateLocked(key);
+ if (settingsState != null) {
+ List<String> changedSettings =
+ settingsState.setSettingsLocked(prefix, keyValues, packageName);
+ if (!changedSettings.isEmpty()) {
+ notifyForConfigSettingsChangeLocked(key, prefix, changedSettings);
+ }
+ }
+
+ return settingsState != null;
+ }
+
public boolean deleteSettingLocked(int type, int userId, String name, boolean forceNotify,
Set<String> criticalSettings) {
final int key = makeKey(type, userId);
@@ -3043,6 +3085,28 @@
mHandler.obtainMessage(MyHandler.MSG_NOTIFY_DATA_CHANGED).sendToTarget();
}
+ private void notifyForConfigSettingsChangeLocked(int key, String prefix,
+ List<String> changedSettings) {
+
+ // Increment the generation first, so observers always see the new value
+ mGenerationRegistry.incrementGeneration(key);
+
+ StringBuilder stringBuilder = new StringBuilder(prefix);
+ for (int i = 0; i < changedSettings.size(); ++i) {
+ stringBuilder.append(changedSettings.get(i).split("/")[1]).append("/");
+ }
+
+ final long token = Binder.clearCallingIdentity();
+ try {
+ notifySettingChangeForRunningUsers(key, stringBuilder.toString());
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+
+ // Always notify that our data changed
+ mHandler.obtainMessage(MyHandler.MSG_NOTIFY_DATA_CHANGED).sendToTarget();
+ }
+
private void maybeNotifyProfiles(int type, int userId, Uri uri, String name,
Collection<String> keysCloned) {
if (keysCloned.contains(name)) {
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
index de6a3a8..4731e68 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
@@ -64,6 +64,7 @@
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
+import java.util.Map;
import java.util.Objects;
/**
@@ -416,6 +417,57 @@
}
// The settings provider must hold its lock when calling here.
+ // Returns the list of keys which changed (added, updated, or deleted).
+ @GuardedBy("mLock")
+ public List<String> setSettingsLocked(String prefix, Map<String, String> keyValues,
+ String packageName) {
+ List<String> changedKeys = new ArrayList<>();
+ // Delete old keys with the prefix that are not part of the new set.
+ for (int i = 0; i < mSettings.keySet().size(); ++i) {
+ String key = mSettings.keyAt(i);
+ if (key.startsWith(prefix) && !keyValues.containsKey(key)) {
+ Setting oldState = mSettings.remove(key);
+
+ StatsLog.write(StatsLog.SETTING_CHANGED, key, /* value= */ "", /* newValue= */ "",
+ oldState.value, /* tag */ "", false, getUserIdFromKey(mKey),
+ StatsLog.SETTING_CHANGED__REASON__DELETED);
+ addHistoricalOperationLocked(HISTORICAL_OPERATION_DELETE, oldState);
+ changedKeys.add(key); // key was removed
+ }
+ }
+
+ // Update/add new keys
+ for (String key : keyValues.keySet()) {
+ String value = keyValues.get(key);
+ String oldValue = null;
+ Setting state = mSettings.get(key);
+ if (state == null) {
+ state = new Setting(key, value, false, packageName, null);
+ mSettings.put(key, state);
+ changedKeys.add(key); // key was added
+ } else if (state.value != value) {
+ oldValue = state.value;
+ state.update(value, false, packageName, null, true);
+ changedKeys.add(key); // key was updated
+ } else {
+ // this key/value already exists, no change and no logging necessary
+ continue;
+ }
+
+ StatsLog.write(StatsLog.SETTING_CHANGED, key, value, state.value, oldValue,
+ /* tag */ null, /* make default */ false,
+ getUserIdFromKey(mKey), StatsLog.SETTING_CHANGED__REASON__UPDATED);
+ addHistoricalOperationLocked(HISTORICAL_OPERATION_UPDATE, state);
+ }
+
+ if (!changedKeys.isEmpty()) {
+ scheduleWriteIfNeededLocked();
+ }
+
+ return changedKeys;
+ }
+
+ // The settings provider must hold its lock when calling here.
public void persistSyncLocked() {
mHandler.removeMessages(MyHandler.MSG_PERSIST_SETTINGS);
doWriteState();
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/WifiSoftApBandChangedNotifier.java b/packages/SettingsProvider/src/com/android/providers/settings/WifiSoftApBandChangedNotifier.java
new file mode 100644
index 0000000..d0d4956
--- /dev/null
+++ b/packages/SettingsProvider/src/com/android/providers/settings/WifiSoftApBandChangedNotifier.java
@@ -0,0 +1,88 @@
+/*
+ * 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 android.app.Notification;
+import android.app.NotificationChannel;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.Resources;
+
+import com.android.internal.messages.nano.SystemMessageProto;
+import com.android.internal.notification.SystemNotificationChannels;
+
+/**
+ * Helper class for sending notifications when the user's Soft AP Band was changed upon restore.
+ */
+public class WifiSoftApBandChangedNotifier {
+ private WifiSoftApBandChangedNotifier() {}
+
+ /**
+ * Send a notification informing the user that their' Soft AP Band was changed upon restore.
+ * When the user taps on the notification, they are taken to the Wifi Tethering page in
+ * Settings.
+ */
+ public static void notifyUserOfApBandConversion(Context context) {
+ NotificationManager notificationManager =
+ context.getSystemService(NotificationManager.class);
+
+ // create channel, or update it if it already exists
+ NotificationChannel channel = new NotificationChannel(
+ SystemNotificationChannels.NETWORK_STATUS,
+ context.getString(android.R.string.notification_channel_network_status),
+ NotificationManager.IMPORTANCE_LOW);
+ notificationManager.createNotificationChannel(channel);
+
+ notificationManager.notify(
+ SystemMessageProto.SystemMessage.NOTE_SOFTAP_CONFIG_CHANGED,
+ createConversionNotification(context));
+ }
+
+ private static Notification createConversionNotification(Context context) {
+ Resources resources = context.getResources();
+ CharSequence title = resources.getText(R.string.wifi_softap_config_change);
+ CharSequence contentSummary = resources.getText(R.string.wifi_softap_config_change_summary);
+ CharSequence content = resources.getText(R.string.wifi_softap_config_change_detailed);
+ int color = resources.getColor(
+ android.R.color.system_notification_accent_color, context.getTheme());
+
+ return new Notification.Builder(context, SystemNotificationChannels.NETWORK_STATUS)
+ .setSmallIcon(R.drawable.ic_wifi_settings)
+ .setPriority(Notification.PRIORITY_HIGH)
+ .setCategory(Notification.CATEGORY_SYSTEM)
+ .setContentTitle(title)
+ .setContentText(contentSummary)
+ .setContentIntent(getPendingActivity(context))
+ .setTicker(title)
+ .setShowWhen(false)
+ .setLocalOnly(true)
+ .setColor(color)
+ .setStyle(new Notification.BigTextStyle()
+ .bigText(content)
+ .setBigContentTitle(title)
+ .setSummaryText(contentSummary))
+ .setAutoCancel(true)
+ .build();
+ }
+
+ private static PendingIntent getPendingActivity(Context context) {
+ Intent intent = new Intent("com.android.settings.WIFI_TETHER_SETTINGS")
+ .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ return PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
+ }
+}
diff --git a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
index 289ac80..7b022a2 100644
--- a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
+++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
@@ -662,7 +662,6 @@
Settings.Secure.NIGHT_DISPLAY_LAST_ACTIVATED_TIME,
Settings.Secure.NUM_ROTATION_SUGGESTIONS_ACCEPTED,
Settings.Secure.ODI_CAPTIONS_ENABLED,
- Settings.Secure.PACKAGE_VERIFIER_USER_CONSENT,
Settings.Secure.PARENTAL_CONTROL_LAST_UPDATE,
Settings.Secure.PAYMENT_SERVICE_SEARCH_URI,
Settings.Secure.PRINT_SERVICE_SEARCH_URI,
diff --git a/packages/SystemUI/res/layout/notif_half_shelf.xml b/packages/SystemUI/res/layout/notif_half_shelf.xml
index 26c8872..d36c1a8 100644
--- a/packages/SystemUI/res/layout/notif_half_shelf.xml
+++ b/packages/SystemUI/res/layout/notif_half_shelf.xml
@@ -46,7 +46,9 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="8dp"
- android:orientation="horizontal" >
+ android:orientation="horizontal"
+ android:clickable="true"
+ android:foreground="?android:attr/selectableItemBackground" >
<ImageView
android:id="@+id/icon"
diff --git a/packages/SystemUI/res/layout/notif_half_shelf_row.xml b/packages/SystemUI/res/layout/notif_half_shelf_row.xml
index b95d5e9..c863e02 100644
--- a/packages/SystemUI/res/layout/notif_half_shelf_row.xml
+++ b/packages/SystemUI/res/layout/notif_half_shelf_row.xml
@@ -20,7 +20,9 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="8dp"
- android:orientation="horizontal" >
+ android:clickable="true"
+ android:orientation="horizontal"
+ android:foreground="?android:attr/selectableItemBackground" >
<!-- This is where an icon would go *if we wanted one* **wink** -->
<Space
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index c3f410e..86ef031 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -125,7 +125,7 @@
<!-- The tiles to display in QuickSettings in retail mode -->
<string name="quick_settings_tiles_retail_mode" translatable="false">
- cell,battery,dnd,flashlight,rotation,location
+ night,dark,dnd,flashlight,rotation,location
</string>
<!-- Whether or not the RSSI tile is capitalized or not. -->
diff --git a/packages/SystemUI/src/com/android/systemui/broadcast/UserBroadcastDispatcher.kt b/packages/SystemUI/src/com/android/systemui/broadcast/UserBroadcastDispatcher.kt
index d50666c..b2942bb 100644
--- a/packages/SystemUI/src/com/android/systemui/broadcast/UserBroadcastDispatcher.kt
+++ b/packages/SystemUI/src/com/android/systemui/broadcast/UserBroadcastDispatcher.kt
@@ -28,6 +28,7 @@
import android.util.ArraySet
import android.util.Log
import androidx.annotation.MainThread
+import androidx.annotation.VisibleForTesting
import com.android.internal.util.Preconditions
import com.android.systemui.Dumpable
import java.io.FileDescriptor
@@ -78,6 +79,14 @@
private val actionsToReceivers = ArrayMap<String, MutableSet<ReceiverData>>()
private val receiverToReceiverData = ArrayMap<BroadcastReceiver, MutableSet<ReceiverData>>()
+ @VisibleForTesting
+ internal fun isReceiverReferenceHeld(receiver: BroadcastReceiver): Boolean {
+ return receiverToReceiverData.contains(receiver) ||
+ actionsToReceivers.any {
+ it.value.any { it.receiver == receiver }
+ }
+ }
+
// Only call on BG thread as it reads from the maps
private fun createFilter(): IntentFilter {
Preconditions.checkState(bgHandler.looper.isCurrentThread,
@@ -142,7 +151,7 @@
if (DEBUG) Log.w(TAG, "Unregister receiver: $receiver")
val actions = receiverToReceiverData.getOrElse(receiver) { return }
.flatMap { it.filter.actionsIterator().asSequence().asIterable() }.toSet()
- receiverToReceiverData.get(receiver)?.clear()
+ receiverToReceiverData.remove(receiver)?.clear()
var changed = false
actions.forEach { action ->
actionsToReceivers.get(action)?.removeIf { it.receiver == receiver }
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
index 51c2ddc..b5845947 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
@@ -419,9 +419,7 @@
new GlobalActionsPanelPlugin.Callbacks() {
@Override
public void dismissGlobalActionsMenu() {
- if (mDialog != null) {
- mDialog.dismiss();
- }
+ dismissDialog();
}
@Override
@@ -916,6 +914,9 @@
/** {@inheritDoc} */
public void onDismiss(DialogInterface dialog) {
+ if (mDialog == dialog) {
+ mDialog = null;
+ }
mWindowManagerFuncs.onGlobalActionsHidden();
if (mShowSilentToggle) {
try {
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 7fb5207..ff34be0 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
@@ -90,7 +90,8 @@
public QSCustomizer(Context context, AttributeSet attrs,
LightBarController lightBarController,
KeyguardStateController keyguardStateController,
- ScreenLifecycle screenLifecycle) {
+ ScreenLifecycle screenLifecycle,
+ TileQueryHelper tileQueryHelper) {
super(new ContextThemeWrapper(context, R.style.edit_theme), attrs);
LayoutInflater.from(getContext()).inflate(R.layout.qs_customize_panel_content, this);
@@ -113,7 +114,8 @@
mRecyclerView = findViewById(android.R.id.list);
mTransparentView = findViewById(R.id.customizer_transparent_view);
mTileAdapter = new TileAdapter(getContext());
- mTileQueryHelper = new TileQueryHelper(context, mTileAdapter);
+ mTileQueryHelper = tileQueryHelper;
+ mTileQueryHelper.setListener(mTileAdapter);
mRecyclerView.setAdapter(mTileAdapter);
mTileAdapter.getItemTouchHelper().attachToRecyclerView(mRecyclerView);
GridLayoutManager layout = new GridLayoutManager(getContext(), 3);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java b/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java
index 7006249..0a9100f 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java
@@ -33,8 +33,9 @@
import android.util.ArraySet;
import android.widget.Button;
-import com.android.systemui.Dependency;
import com.android.systemui.R;
+import com.android.systemui.dagger.qualifiers.BgHandler;
+import com.android.systemui.dagger.qualifiers.MainHandler;
import com.android.systemui.plugins.qs.QSTile;
import com.android.systemui.plugins.qs.QSTile.State;
import com.android.systemui.qs.QSTileHost;
@@ -47,6 +48,8 @@
import java.util.Collection;
import java.util.List;
+import javax.inject.Inject;
+
public class TileQueryHelper {
private static final String TAG = "TileQueryHelper";
@@ -55,15 +58,20 @@
private final Handler mBgHandler;
private final Handler mMainHandler;
private final Context mContext;
- private final TileStateListener mListener;
+ private TileStateListener mListener;
private boolean mFinished;
- public TileQueryHelper(Context context, TileStateListener listener) {
+ @Inject
+ public TileQueryHelper(Context context,
+ @MainHandler Handler mainHandler, @BgHandler Handler bgHandler) {
mContext = context;
+ mMainHandler = mainHandler;
+ mBgHandler = bgHandler;
+ }
+
+ public void setListener(TileStateListener listener) {
mListener = listener;
- mBgHandler = new Handler(Dependency.get(Dependency.BG_LOOPER));
- mMainHandler = Dependency.get(Dependency.MAIN_HANDLER);
}
public void queryTiles(QSTileHost host) {
@@ -178,7 +186,9 @@
private void notifyTilesChanged(final boolean finished) {
final ArrayList<TileInfo> tilesToReturn = new ArrayList<>(mTiles);
mMainHandler.post(() -> {
- mListener.onTilesChanged(tilesToReturn);
+ if (mListener != null) {
+ mListener.onTilesChanged(tilesToReturn);
+ }
mFinished = finished;
});
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/NfcTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/NfcTile.java
index 8bbfd24..f0140ba 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/NfcTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/NfcTile.java
@@ -132,7 +132,7 @@
private NfcAdapter getAdapter() {
if (mAdapter == null) {
try {
- mAdapter = NfcAdapter.getNfcAdapter(mContext);
+ mAdapter = NfcAdapter.getDefaultAdapter(mContext);
} catch (UnsupportedOperationException e) {
mAdapter = null;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ChannelEditorListView.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ChannelEditorListView.kt
index 6faf77e..983315e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ChannelEditorListView.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ChannelEditorListView.kt
@@ -129,6 +129,8 @@
iconView = findViewById(R.id.icon)
channelName = findViewById(R.id.app_name)
switch = findViewById(R.id.toggle)
+
+ setOnClickListener { switch.toggle() }
}
}
@@ -156,6 +158,7 @@
controller.proposeEditForChannel(it, if (b) it.importance else IMPORTANCE_NONE)
}
}
+ setOnClickListener { switch.toggle() }
}
private fun updateViews() {
diff --git a/packages/SystemUI/src/com/android/systemui/wm/DisplayWindowController.java b/packages/SystemUI/src/com/android/systemui/wm/DisplayWindowController.java
index f3487fb..19fff79 100644
--- a/packages/SystemUI/src/com/android/systemui/wm/DisplayWindowController.java
+++ b/packages/SystemUI/src/com/android/systemui/wm/DisplayWindowController.java
@@ -16,8 +16,10 @@
package com.android.systemui.wm;
+import android.content.res.Configuration;
import android.os.Handler;
import android.os.RemoteException;
+import android.util.Slog;
import android.util.SparseArray;
import android.view.IDisplayWindowListener;
import android.view.IDisplayWindowRotationCallback;
@@ -40,6 +42,8 @@
*/
@Singleton
public class DisplayWindowController {
+ private static final String TAG = "DisplayWindowController";
+
private final Handler mHandler;
private final ArrayList<OnDisplayWindowRotationController> mRotationControllers =
@@ -84,8 +88,26 @@
DisplayRecord record = new DisplayRecord();
record.mDisplayId = displayId;
mDisplays.put(displayId, record);
- for (DisplayWindowListener l : mDisplayChangedListeners) {
- l.onDisplayAdded(displayId);
+ for (int i = 0; i < mDisplayChangedListeners.size(); ++i) {
+ mDisplayChangedListeners.get(i).onDisplayAdded(displayId);
+ }
+ }
+ });
+ }
+
+ @Override
+ public void onDisplayConfigurationChanged(int displayId, Configuration newConfig) {
+ mHandler.post(() -> {
+ synchronized (mDisplays) {
+ DisplayRecord dr = mDisplays.get(displayId);
+ if (dr == null) {
+ Slog.w(TAG, "Skipping Display Configuration change on non-added"
+ + " display.");
+ return;
+ }
+ for (int i = 0; i < mDisplayChangedListeners.size(); ++i) {
+ mDisplayChangedListeners.get(i).onDisplayConfigurationChanged(
+ displayId, newConfig);
}
}
});
@@ -118,8 +140,8 @@
}
/**
- * Add a display window-container listener. It will get notified when displays are
- * added/removed from the WM hierarchy.
+ * Add a display window-container listener. It will get notified whenever a display's
+ * configuration changes or when displays are added/removed from the WM hierarchy.
*/
public void addDisplayWindowListener(DisplayWindowListener listener) {
synchronized (mDisplays) {
@@ -165,7 +187,8 @@
}
/**
- * Gets notified when a display is added/removed to the WM hierarchy.
+ * Gets notified when a display is added/removed to the WM hierarchy and when a display's
+ * window-configuration changes.
*
* @see IDisplayWindowListener
*/
@@ -176,6 +199,11 @@
void onDisplayAdded(int displayId);
/**
+ * Called when a display's window-container configuration changes.
+ */
+ void onDisplayConfigurationChanged(int displayId, Configuration newConfig);
+
+ /**
* Called when a display is removed.
*/
void onDisplayRemoved(int displayId);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/broadcast/UserBroadcastDispatcherTest.kt b/packages/SystemUI/tests/src/com/android/systemui/broadcast/UserBroadcastDispatcherTest.kt
index e838d9e..21ed155 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/broadcast/UserBroadcastDispatcherTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/broadcast/UserBroadcastDispatcherTest.kt
@@ -77,7 +77,7 @@
private lateinit var argumentCaptor: ArgumentCaptor<IntentFilter>
private lateinit var testableLooper: TestableLooper
- private lateinit var universalBroadcastReceiver: UserBroadcastDispatcher
+ private lateinit var userBroadcastDispatcher: UserBroadcastDispatcher
private lateinit var intentFilter: IntentFilter
private lateinit var intentFilterOther: IntentFilter
private lateinit var handler: Handler
@@ -88,9 +88,9 @@
testableLooper = TestableLooper.get(this)
handler = Handler(testableLooper.looper)
- universalBroadcastReceiver = UserBroadcastDispatcher(
+ userBroadcastDispatcher = UserBroadcastDispatcher(
mockContext, USER_ID, handler, testableLooper.looper)
- universalBroadcastReceiver.pendingResult = mPendingResult
+ userBroadcastDispatcher.pendingResult = mPendingResult
}
@Test
@@ -107,11 +107,11 @@
fun testSingleReceiverRegistered() {
intentFilter = IntentFilter(ACTION_1)
- universalBroadcastReceiver.registerReceiver(
+ userBroadcastDispatcher.registerReceiver(
ReceiverData(broadcastReceiver, intentFilter, mockHandler, USER_HANDLE))
testableLooper.processAllMessages()
- assertTrue(universalBroadcastReceiver.isRegistered())
+ assertTrue(userBroadcastDispatcher.isRegistered())
verify(mockContext).registerReceiverAsUser(
any(),
eq(USER_HANDLE),
@@ -127,19 +127,19 @@
fun testSingleReceiverUnregistered() {
intentFilter = IntentFilter(ACTION_1)
- universalBroadcastReceiver.registerReceiver(
+ userBroadcastDispatcher.registerReceiver(
ReceiverData(broadcastReceiver, intentFilter, mockHandler, USER_HANDLE))
testableLooper.processAllMessages()
reset(mockContext)
- assertTrue(universalBroadcastReceiver.isRegistered())
+ assertTrue(userBroadcastDispatcher.isRegistered())
- universalBroadcastReceiver.unregisterReceiver(broadcastReceiver)
+ userBroadcastDispatcher.unregisterReceiver(broadcastReceiver)
testableLooper.processAllMessages()
verify(mockContext, atLeastOnce()).unregisterReceiver(any())
verify(mockContext, never()).registerReceiverAsUser(any(), any(), any(), any(), any())
- assertFalse(universalBroadcastReceiver.isRegistered())
+ assertFalse(userBroadcastDispatcher.isRegistered())
}
@Test
@@ -150,13 +150,13 @@
addCategory(CATEGORY_2)
}
- universalBroadcastReceiver.registerReceiver(
+ userBroadcastDispatcher.registerReceiver(
ReceiverData(broadcastReceiver, intentFilter, mockHandler, USER_HANDLE))
- universalBroadcastReceiver.registerReceiver(
+ userBroadcastDispatcher.registerReceiver(
ReceiverData(broadcastReceiverOther, intentFilterOther, mockHandler, USER_HANDLE))
testableLooper.processAllMessages()
- assertTrue(universalBroadcastReceiver.isRegistered())
+ assertTrue(userBroadcastDispatcher.isRegistered())
verify(mockContext, times(2)).registerReceiverAsUser(
any(),
@@ -178,14 +178,14 @@
intentFilter = IntentFilter(ACTION_1)
intentFilterOther = IntentFilter(ACTION_2)
- universalBroadcastReceiver.registerReceiver(
+ userBroadcastDispatcher.registerReceiver(
ReceiverData(broadcastReceiver, intentFilter, handler, USER_HANDLE))
- universalBroadcastReceiver.registerReceiver(
+ userBroadcastDispatcher.registerReceiver(
ReceiverData(broadcastReceiverOther, intentFilterOther, handler, USER_HANDLE))
val intent = Intent(ACTION_2)
- universalBroadcastReceiver.onReceive(mockContext, intent)
+ userBroadcastDispatcher.onReceive(mockContext, intent)
testableLooper.processAllMessages()
verify(broadcastReceiver, never()).onReceive(any(), any())
@@ -197,14 +197,14 @@
intentFilter = IntentFilter(ACTION_1)
intentFilterOther = IntentFilter(ACTION_2)
- universalBroadcastReceiver.registerReceiver(
+ userBroadcastDispatcher.registerReceiver(
ReceiverData(broadcastReceiver, intentFilter, handler, USER_HANDLE))
- universalBroadcastReceiver.registerReceiver(
+ userBroadcastDispatcher.registerReceiver(
ReceiverData(broadcastReceiver, intentFilterOther, handler, USER_HANDLE))
val intent = Intent(ACTION_2)
- universalBroadcastReceiver.onReceive(mockContext, intent)
+ userBroadcastDispatcher.onReceive(mockContext, intent)
testableLooper.processAllMessages()
verify(broadcastReceiver).onReceive(mockContext, intent)
@@ -217,14 +217,14 @@
intentFilterOther = IntentFilter(ACTION_1)
intentFilterOther.addCategory(CATEGORY_2)
- universalBroadcastReceiver.registerReceiver(
+ userBroadcastDispatcher.registerReceiver(
ReceiverData(broadcastReceiver, intentFilter, handler, USER_HANDLE))
- universalBroadcastReceiver.registerReceiver(
+ userBroadcastDispatcher.registerReceiver(
ReceiverData(broadcastReceiverOther, intentFilterOther, handler, USER_HANDLE))
val intent = Intent(ACTION_1)
- universalBroadcastReceiver.onReceive(mockContext, intent)
+ userBroadcastDispatcher.onReceive(mockContext, intent)
testableLooper.processAllMessages()
verify(broadcastReceiver).onReceive(mockContext, intent)
@@ -234,15 +234,32 @@
@Test
fun testPendingResult() {
intentFilter = IntentFilter(ACTION_1)
- universalBroadcastReceiver.registerReceiver(
+ userBroadcastDispatcher.registerReceiver(
ReceiverData(broadcastReceiver, intentFilter, handler, USER_HANDLE))
val intent = Intent(ACTION_1)
- universalBroadcastReceiver.onReceive(mockContext, intent)
+ userBroadcastDispatcher.onReceive(mockContext, intent)
testableLooper.processAllMessages()
verify(broadcastReceiver).onReceive(mockContext, intent)
verify(broadcastReceiver).pendingResult = mPendingResult
}
+
+ @Test
+ fun testRemoveReceiverReferences() {
+ intentFilter = IntentFilter(ACTION_1)
+ userBroadcastDispatcher.registerReceiver(
+ ReceiverData(broadcastReceiver, intentFilter, handler, USER_HANDLE))
+
+ intentFilterOther = IntentFilter(ACTION_1)
+ intentFilterOther.addAction(ACTION_2)
+ userBroadcastDispatcher.registerReceiver(
+ ReceiverData(broadcastReceiverOther, intentFilterOther, handler, USER_HANDLE))
+
+ userBroadcastDispatcher.unregisterReceiver(broadcastReceiver)
+ testableLooper.processAllMessages()
+
+ assertFalse(userBroadcastDispatcher.isReceiverReferenceHeld(broadcastReceiver))
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/customize/TileQueryHelperTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/customize/TileQueryHelperTest.java
index 9e226f6..b41512c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/customize/TileQueryHelperTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/customize/TileQueryHelperTest.java
@@ -36,6 +36,8 @@
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
+import android.os.Handler;
+import android.os.Looper;
import android.provider.Settings;
import android.service.quicksettings.Tile;
import android.testing.AndroidTestingRunner;
@@ -46,7 +48,6 @@
import androidx.test.filters.SmallTest;
-import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.plugins.qs.QSTile;
@@ -99,12 +100,12 @@
private QSTile.State mState;
private TestableLooper mBGLooper;
private TileQueryHelper mTileQueryHelper;
+ private Handler mMainHandler;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
mBGLooper = TestableLooper.get(this);
- mDependency.injectTestDependency(Dependency.BG_LOOPER, mBGLooper.getLooper());
mContext.setMockPackageManager(mPackageManager);
mState = new QSTile.State();
@@ -122,7 +123,10 @@
}
).when(mQSTileHost).createTile(anyString());
- mTileQueryHelper = new TileQueryHelper(mContext, mListener);
+ mMainHandler = new Handler(Looper.getMainLooper());
+ mTileQueryHelper = new TileQueryHelper(mContext, mMainHandler,
+ new Handler(mBGLooper.getLooper()));
+ mTileQueryHelper.setListener(mListener);
}
@Test
@@ -135,7 +139,7 @@
mTileQueryHelper.queryTiles(mQSTileHost);
mBGLooper.processAllMessages();
- waitForIdleSync(Dependency.get(Dependency.MAIN_HANDLER));
+ waitForIdleSync(mMainHandler);
assertTrue(mTileQueryHelper.isFinished());
}
@@ -145,7 +149,7 @@
mTileQueryHelper.queryTiles(mQSTileHost);
mBGLooper.processAllMessages();
- waitForIdleSync(Dependency.get(Dependency.MAIN_HANDLER));
+ waitForIdleSync(mMainHandler);
verify(mListener, times(2)).onTilesChanged(any());
}
@@ -160,7 +164,7 @@
mTileQueryHelper.queryTiles(mQSTileHost);
mBGLooper.processAllMessages();
- waitForIdleSync(Dependency.get(Dependency.MAIN_HANDLER));
+ waitForIdleSync(mMainHandler);
assertTrue(mTileQueryHelper.isFinished());
}
@@ -175,7 +179,7 @@
mTileQueryHelper.queryTiles(mQSTileHost);
mBGLooper.processAllMessages();
- waitForIdleSync(Dependency.get(Dependency.MAIN_HANDLER));
+ waitForIdleSync(mMainHandler);
verify(mListener, atLeastOnce()).onTilesChanged(mCaptor.capture());
List<String> specs = new ArrayList<>();
@@ -196,7 +200,7 @@
mTileQueryHelper.queryTiles(mQSTileHost);
mBGLooper.processAllMessages();
- waitForIdleSync(Dependency.get(Dependency.MAIN_HANDLER));
+ waitForIdleSync(mMainHandler);
verify(mListener, atLeastOnce()).onTilesChanged(mCaptor.capture());
List<String> specs = new ArrayList<>();
@@ -217,7 +221,7 @@
mTileQueryHelper.queryTiles(mQSTileHost);
mBGLooper.processAllMessages();
- waitForIdleSync(Dependency.get(Dependency.MAIN_HANDLER));
+ waitForIdleSync(mMainHandler);
verify(mListener, atLeastOnce()).onTilesChanged(mCaptor.capture());
List<String> specs = new ArrayList<>();
@@ -248,7 +252,7 @@
mTileQueryHelper.queryTiles(mQSTileHost);
mBGLooper.processAllMessages();
- waitForIdleSync(Dependency.get(Dependency.MAIN_HANDLER));
+ waitForIdleSync(mMainHandler);
verify(mListener, atLeastOnce()).onTilesChanged(mCaptor.capture());
List<TileQueryHelper.TileInfo> tileInfos = mCaptor.getValue();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
index 4d86613..61a7cc7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
@@ -139,6 +139,14 @@
when(mMockCm.getDefaultNetworkCapabilitiesForUser(0)).thenReturn(
new NetworkCapabilities[] { mNetCapabilities });
when(mMockTm.createForSubscriptionId(anyInt())).thenReturn(mMockTm);
+ doAnswer(invocation -> {
+ int rssi = invocation.getArgument(0);
+ if (rssi < -88) return 0;
+ if (rssi < -77) return 1;
+ if (rssi < -66) return 2;
+ if (rssi < -55) return 3;
+ return 4;
+ }).when(mMockWm).calculateSignalLevel(anyInt());
mSignalStrength = mock(SignalStrength.class);
mServiceState = mock(ServiceState.class);
diff --git a/packages/Tethering/Android.bp b/packages/Tethering/Android.bp
index 61bfb92..7b35f4d 100644
--- a/packages/Tethering/Android.bp
+++ b/packages/Tethering/Android.bp
@@ -20,12 +20,14 @@
srcs: [
"src/**/*.java",
":framework-tethering-shared-srcs",
+ ":net-module-utils-srcs",
":services-tethering-shared-srcs",
":servicescore-tethering-src",
],
static_libs: [
"androidx.annotation_annotation",
"netd_aidl_interface-java",
+ "netlink-client",
"networkstack-aidl-interfaces-java",
"android.hardware.tetheroffload.control-V1.0-java",
"tethering-client",
diff --git a/services/Android.bp b/services/Android.bp
index 6953e86..35dc44e 100644
--- a/services/Android.bp
+++ b/services/Android.bp
@@ -1,3 +1,38 @@
+filegroup {
+ name: "services-main-sources",
+ srcs: ["java/**/*.java"],
+ path: "java",
+ visibility: ["//visibility:private"],
+}
+
+filegroup {
+ name: "services-sources",
+ srcs: [
+ ":services.core-sources",
+ ":services.accessibility-sources",
+ ":services.appprediction-sources",
+ ":services.appwidget-sources",
+ ":services.autofill-sources",
+ ":services.backup-sources",
+ ":services.companion-sources",
+ ":services.contentcapture-sources",
+ ":services.contentsuggestions-sources",
+ ":services.coverage-sources",
+ ":services.devicepolicy-sources",
+ ":services.midi-sources",
+ ":services.net-sources",
+ ":services.print-sources",
+ ":services.restrictions-sources",
+ ":services.startop.iorap-sources",
+ ":services.systemcaptions-sources",
+ ":services.usage-sources",
+ ":services.usb-sources",
+ ":services.voiceinteraction-sources",
+ ":services.wifi-sources",
+ ],
+ visibility: ["//visibility:private"],
+}
+
// merge all required services into one jar
// ============================================================
java_library {
@@ -9,9 +44,7 @@
profile: "art-profile",
},
- srcs: [
- "java/**/*.java",
- ],
+ srcs: [":services-main-sources"],
// The convention is to name each service module 'services.$(module_name)'
static_libs: [
diff --git a/services/accessibility/Android.bp b/services/accessibility/Android.bp
index f991d7b..284a2f2 100644
--- a/services/accessibility/Android.bp
+++ b/services/accessibility/Android.bp
@@ -1,5 +1,12 @@
+filegroup {
+ name: "services.accessibility-sources",
+ srcs: ["java/**/*.java"],
+ path: "java",
+ visibility: ["//frameworks/base/services"],
+}
+
java_library_static {
name: "services.accessibility",
- srcs: ["java/**/*.java"],
+ srcs: [":services.accessibility-sources"],
libs: ["services.core"],
}
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityWindowManager.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityWindowManager.java
index cb858ac..339fc96 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityWindowManager.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityWindowManager.java
@@ -1217,8 +1217,8 @@
if (mAccessibilityFocusedWindowId != windowId) {
clearAccessibilityFocusLocked(mAccessibilityFocusedWindowId);
setAccessibilityFocusedWindowLocked(windowId);
- mAccessibilityFocusNodeId = nodeId;
}
+ mAccessibilityFocusNodeId = nodeId;
}
} break;
diff --git a/services/appprediction/Android.bp b/services/appprediction/Android.bp
index a7be587..e14e1df 100644
--- a/services/appprediction/Android.bp
+++ b/services/appprediction/Android.bp
@@ -1,5 +1,12 @@
+filegroup {
+ name: "services.appprediction-sources",
+ srcs: ["java/**/*.java"],
+ path: "java",
+ visibility: ["//frameworks/base/services"],
+}
+
java_library_static {
name: "services.appprediction",
- srcs: ["java/**/*.java"],
+ srcs: [":services.appprediction-sources"],
libs: ["services.core"],
}
diff --git a/services/appwidget/Android.bp b/services/appwidget/Android.bp
index aad2ad19..54cf6ce 100644
--- a/services/appwidget/Android.bp
+++ b/services/appwidget/Android.bp
@@ -1,5 +1,12 @@
+filegroup {
+ name: "services.appwidget-sources",
+ srcs: ["java/**/*.java"],
+ path: "java",
+ visibility: ["//frameworks/base/services"],
+}
+
java_library_static {
name: "services.appwidget",
- srcs: ["java/**/*.java"],
+ srcs: [":services.appwidget-sources"],
libs: ["services.core"],
}
diff --git a/services/autofill/Android.bp b/services/autofill/Android.bp
index 2768c18..539eb1a 100644
--- a/services/autofill/Android.bp
+++ b/services/autofill/Android.bp
@@ -1,5 +1,12 @@
+filegroup {
+ name: "services.autofill-sources",
+ srcs: ["java/**/*.java"],
+ path: "java",
+ visibility: ["//frameworks/base/services"],
+}
+
java_library_static {
name: "services.autofill",
- srcs: ["java/**/*.java"],
+ srcs: [":services.autofill-sources"],
libs: ["services.core"],
}
diff --git a/services/backup/Android.bp b/services/backup/Android.bp
index a3b0c89..f02da20 100644
--- a/services/backup/Android.bp
+++ b/services/backup/Android.bp
@@ -1,6 +1,13 @@
+filegroup {
+ name: "services.backup-sources",
+ srcs: ["java/**/*.java"],
+ path: "java",
+ visibility: ["//frameworks/base/services"],
+}
+
java_library_static {
name: "services.backup",
- srcs: ["java/**/*.java"],
+ srcs: [":services.backup-sources"],
libs: ["services.core"],
static_libs: ["backuplib"],
}
diff --git a/services/backup/backuplib/Android.bp b/services/backup/backuplib/Android.bp
index 7b194a092..00f51c9 100644
--- a/services/backup/backuplib/Android.bp
+++ b/services/backup/backuplib/Android.bp
@@ -1,5 +1,12 @@
+filegroup {
+ name: "backuplib-sources",
+ srcs: ["java/**/*.java"],
+ path: "java",
+ visibility: ["//frameworks/base/services"],
+}
+
java_library {
name: "backuplib",
- srcs: ["java/**/*.java"],
+ srcs: [":backuplib-sources"],
libs: ["services.core"],
}
diff --git a/services/companion/Android.bp b/services/companion/Android.bp
index d2dac35..9677a7d 100644
--- a/services/companion/Android.bp
+++ b/services/companion/Android.bp
@@ -1,5 +1,12 @@
+filegroup {
+ name: "services.companion-sources",
+ srcs: ["java/**/*.java"],
+ path: "java",
+ visibility: ["//frameworks/base/services"],
+}
+
java_library_static {
name: "services.companion",
- srcs: ["java/**/*.java"],
+ srcs: [":services.companion-sources"],
libs: ["services.core"],
}
diff --git a/services/contentcapture/Android.bp b/services/contentcapture/Android.bp
index 57e859e..96e2072 100644
--- a/services/contentcapture/Android.bp
+++ b/services/contentcapture/Android.bp
@@ -1,5 +1,12 @@
+filegroup {
+ name: "services.contentcapture-sources",
+ srcs: ["java/**/*.java"],
+ path: "java",
+ visibility: ["//frameworks/base/services"],
+}
+
java_library_static {
name: "services.contentcapture",
- srcs: ["java/**/*.java"],
+ srcs: [":services.contentcapture-sources"],
libs: ["services.core"],
}
diff --git a/services/contentsuggestions/Android.bp b/services/contentsuggestions/Android.bp
index fc09d2e..d17f06f 100644
--- a/services/contentsuggestions/Android.bp
+++ b/services/contentsuggestions/Android.bp
@@ -1,5 +1,12 @@
+filegroup {
+ name: "services.contentsuggestions-sources",
+ srcs: ["java/**/*.java"],
+ path: "java",
+ visibility: ["//frameworks/base/services"],
+}
+
java_library_static {
name: "services.contentsuggestions",
- srcs: ["java/**/*.java"],
+ srcs: [":services.contentsuggestions-sources"],
libs: ["services.core"],
-}
\ No newline at end of file
+}
diff --git a/services/core/Android.bp b/services/core/Android.bp
index b8caefd..594ac10 100644
--- a/services/core/Android.bp
+++ b/services/core/Android.bp
@@ -1,3 +1,10 @@
+filegroup {
+ name: "services.core-sources",
+ srcs: ["java/**/*.java"],
+ path: "java",
+ visibility: ["//frameworks/base/services"],
+}
+
java_library {
name: "protolog-common",
srcs: [
@@ -16,7 +23,10 @@
genrule {
name: "services.core.protologsrc",
- srcs: [":services.core.wm.protologgroups", "java/**/*.java"],
+ srcs: [
+ ":services.core.wm.protologgroups",
+ ":services.core-sources",
+ ],
tools: ["protologtool"],
cmd: "$(location protologtool) transform-protolog-calls " +
"--protolog-class com.android.server.protolog.common.ProtoLog " +
@@ -25,20 +35,23 @@
"--loggroups-class com.android.server.wm.ProtoLogGroup " +
"--loggroups-jar $(location :services.core.wm.protologgroups) " +
"--output-srcjar $(out) " +
- "$(locations java/**/*.java)",
+ "$(locations :services.core-sources)",
out: ["services.core.protolog.srcjar"],
}
genrule {
name: "generate-protolog.json",
- srcs: [":services.core.wm.protologgroups", "java/**/*.java"],
+ srcs: [
+ ":services.core.wm.protologgroups",
+ ":services.core-sources",
+ ],
tools: ["protologtool"],
cmd: "$(location protologtool) generate-viewer-config " +
"--protolog-class com.android.server.protolog.common.ProtoLog " +
"--loggroups-class com.android.server.wm.ProtoLogGroup " +
"--loggroups-jar $(location :services.core.wm.protologgroups) " +
"--viewer-conf $(out) " +
- "$(locations java/**/*.java)",
+ "$(locations :services.core-sources)",
out: ["services.core.protolog.json"],
}
@@ -60,25 +73,15 @@
java_library_static {
name: "services.core.unboosted",
-
- aidl: {
- include_dirs: [
- "frameworks/base/cmds/idmap2/idmap2d/aidl",
- "frameworks/native/aidl/binder",
- "frameworks/native/cmds/dumpstate/binder",
- "system/core/storaged/binder",
- "system/vold/binder",
- "system/gsid/aidl",
- ],
- },
srcs: [
":services.core.protologsrc",
":dumpstate_aidl",
+ ":framework_native_aidl",
+ ":gsiservice_aidl",
":idmap2_aidl",
":installd_aidl",
":storaged_aidl",
":vold_aidl",
- ":gsiservice_aidl",
":platform-compat-config",
":tethering-servicescore-srcs",
"java/com/android/server/EventLogTags.logtags",
diff --git a/services/core/java/android/content/pm/PackageManagerInternal.java b/services/core/java/android/content/pm/PackageManagerInternal.java
index dc24cff..e67d736 100644
--- a/services/core/java/android/content/pm/PackageManagerInternal.java
+++ b/services/core/java/android/content/pm/PackageManagerInternal.java
@@ -22,6 +22,7 @@
import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.content.ComponentName;
+import android.content.ContentResolver;
import android.content.Intent;
import android.content.IntentSender;
import android.content.pm.PackageManager.ApplicationInfoFlags;
@@ -244,12 +245,16 @@
/**
* Retrieve all activities that can be performed for the given intent.
+ * @param resolvedType the resolved type of the intent, which should be resolved via
+ * {@link Intent#resolveTypeIfNeeded(ContentResolver)} before passing to {@link PackageManager}
* @param filterCallingUid The results will be filtered in the context of this UID instead
* of the calling UID.
* @see PackageManager#queryIntentActivities(Intent, int)
*/
- public abstract List<ResolveInfo> queryIntentActivities(Intent intent,
- @ResolveInfoFlags int flags, int filterCallingUid, int userId);
+ public abstract List<ResolveInfo> queryIntentActivities(
+ Intent intent, @Nullable String resolvedType, @ResolveInfoFlags int flags,
+ int filterCallingUid, int userId);
+
/**
* Retrieve all services that can be performed for the given intent.
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index a75d5d69..ce4cdc8 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -2186,6 +2186,11 @@
*/
@VisibleForTesting
public void systemReady() {
+ // Let PermissionMonitor#startMonitoring() running in the beginning of the systemReady
+ // before MultipathPolicyTracker.start(). Since mApps in PermissionMonitor needs to be
+ // populated first to ensure that listening network request which is sent by
+ // MultipathPolicyTracker won't be added NET_CAPABILITY_FOREGROUND capability.
+ mPermissionMonitor.startMonitoring();
mProxyTracker.loadGlobalProxy();
registerNetdEventCallback();
mTethering.systemReady();
@@ -2206,8 +2211,6 @@
mHandler.sendMessage(mHandler.obtainMessage(EVENT_CONFIGURE_ALWAYS_ON_NETWORKS));
mHandler.sendMessage(mHandler.obtainMessage(EVENT_SYSTEM_READY));
-
- mPermissionMonitor.startMonitoring();
}
/**
@@ -3185,7 +3188,7 @@
if (!nai.networkCapabilities.hasTransport(TRANSPORT_VPN)) {
updateAllVpnsCapabilities();
}
- rematchAllNetworksAndRequests(null, 0);
+ rematchAllNetworksAndRequests();
mLingerMonitor.noteDisconnect(nai);
if (nai.created) {
// Tell netd to clean up the configuration for this network
@@ -3271,8 +3274,7 @@
}
}
}
- rematchAllNetworksAndRequests(null, 0);
- ensureRunningOnConnectivityServiceThread();
+ rematchAllNetworksAndRequests();
if (nri.request.isRequest() && nri.mSatisfier == null) {
sendUpdatedScoreToFactories(nri.request, null);
}
@@ -3515,13 +3517,12 @@
}
if (accept != nai.networkMisc.acceptUnvalidated) {
- int oldScore = nai.getCurrentScore();
nai.networkMisc.acceptUnvalidated = accept;
// If network becomes partial connectivity and user already accepted to use this
// network, we should respect the user's option and don't need to popup the
// PARTIAL_CONNECTIVITY notification to user again.
nai.networkMisc.acceptPartialConnectivity = accept;
- rematchAllNetworksAndRequests(nai, oldScore);
+ rematchAllNetworksAndRequests();
sendUpdatedScoreToFactories(nai);
}
@@ -3590,9 +3591,8 @@
return;
}
if (!nai.avoidUnvalidated) {
- int oldScore = nai.getCurrentScore();
nai.avoidUnvalidated = true;
- rematchAllNetworksAndRequests(nai, oldScore);
+ rematchAllNetworksAndRequests();
sendUpdatedScoreToFactories(nai);
}
}
@@ -3693,7 +3693,7 @@
private void rematchForAvoidBadWifiUpdate() {
- rematchAllNetworksAndRequests(null, 0);
+ rematchAllNetworksAndRequests();
for (NetworkAgentInfo nai: mNetworkAgentInfos.values()) {
if (nai.networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
sendUpdatedScoreToFactories(nai);
@@ -5965,7 +5965,7 @@
} else {
// If the requestable capabilities have changed or the score changed, we can't have been
// called by rematchNetworkAndRequests, so it's safe to start a rematch.
- rematchAllNetworksAndRequests(nai, oldScore);
+ rematchAllNetworksAndRequests();
notifyNetworkCallbacks(nai, ConnectivityManager.CALLBACK_CAP_CHANGED);
}
@@ -6294,6 +6294,41 @@
}
}
+ private ArrayMap<NetworkRequestInfo, NetworkAgentInfo> computeRequestReassignmentForNetwork(
+ @NonNull final NetworkAgentInfo newNetwork) {
+ final int score = newNetwork.getCurrentScore();
+ final ArrayMap<NetworkRequestInfo, NetworkAgentInfo> reassignedRequests = new ArrayMap<>();
+ for (NetworkRequestInfo nri : mNetworkRequests.values()) {
+ // Process requests in the first pass and listens in the second pass. This allows us to
+ // change a network's capabilities depending on which requests it has. This is only
+ // correct if the change in capabilities doesn't affect whether the network satisfies
+ // requests or not, and doesn't affect the network's score.
+ if (nri.request.isListen()) continue;
+
+ final NetworkAgentInfo currentNetwork = nri.mSatisfier;
+ final boolean satisfies = newNetwork.satisfies(nri.request);
+ if (newNetwork == currentNetwork && satisfies) continue;
+
+ // check if it satisfies the NetworkCapabilities
+ if (VDBG) log(" checking if request is satisfied: " + nri.request);
+ if (satisfies) {
+ // next check if it's better than any current network we're using for
+ // this request
+ if (VDBG || DDBG) {
+ log("currentScore = "
+ + (currentNetwork != null ? currentNetwork.getCurrentScore() : 0)
+ + ", newScore = " + score);
+ }
+ if (currentNetwork == null || currentNetwork.getCurrentScore() < score) {
+ reassignedRequests.put(nri, newNetwork);
+ }
+ } else if (newNetwork.isSatisfyingRequest(nri.request.requestId)) {
+ reassignedRequests.put(nri, null);
+ }
+ }
+ return reassignedRequests;
+ }
+
// Handles a network appearing or improving its score.
//
// - Evaluates all current NetworkRequests that can be
@@ -6307,10 +6342,6 @@
// - Tears down newNetwork if it just became validated
// but turns out to be unneeded.
//
- // - If reapUnvalidatedNetworks==REAP, tears down unvalidated
- // networks that have no chance (i.e. even if validated)
- // of becoming the highest scoring network.
- //
// NOTE: This function only adds NetworkRequests that "newNetwork" could satisfy,
// it does not remove NetworkRequests that other Networks could better satisfy.
// If you need to handle decreases in score, use {@link rematchAllNetworksAndRequests}.
@@ -6318,11 +6349,8 @@
// as it performs better by a factor of the number of Networks.
//
// @param newNetwork is the network to be matched against NetworkRequests.
- // @param reapUnvalidatedNetworks indicates if an additional pass over all networks should be
- // performed to tear down unvalidated networks that have no chance (i.e. even if
- // validated) of becoming the highest scoring network.
- private void rematchNetworkAndRequests(NetworkAgentInfo newNetwork,
- ReapUnvalidatedNetworks reapUnvalidatedNetworks, long now) {
+ // @param now the time the rematch starts, as returned by SystemClock.elapsedRealtime();
+ private void rematchNetworkAndRequests(NetworkAgentInfo newNetwork, long now) {
ensureRunningOnConnectivityServiceThread();
if (!newNetwork.everConnected) return;
boolean keep = newNetwork.isVPN();
@@ -6334,39 +6362,11 @@
if (VDBG || DDBG) log("rematching " + newNetwork.name());
- final ArrayMap<NetworkRequestInfo, NetworkAgentInfo> reassignedRequests = new ArrayMap<>();
+ final ArrayMap<NetworkRequestInfo, NetworkAgentInfo> reassignedRequests =
+ computeRequestReassignmentForNetwork(newNetwork);
NetworkCapabilities nc = newNetwork.networkCapabilities;
if (VDBG) log(" network has: " + nc);
- for (NetworkRequestInfo nri : mNetworkRequests.values()) {
- // Process requests in the first pass and listens in the second pass. This allows us to
- // change a network's capabilities depending on which requests it has. This is only
- // correct if the change in capabilities doesn't affect whether the network satisfies
- // requests or not, and doesn't affect the network's score.
- if (nri.request.isListen()) continue;
-
- ensureRunningOnConnectivityServiceThread();
- final NetworkAgentInfo currentNetwork = nri.mSatisfier;
- final boolean satisfies = newNetwork.satisfies(nri.request);
- if (newNetwork == currentNetwork && satisfies) continue;
-
- // check if it satisfies the NetworkCapabilities
- if (VDBG) log(" checking if request is satisfied: " + nri.request);
- if (satisfies) {
- // next check if it's better than any current network we're using for
- // this request
- if (VDBG || DDBG) {
- log("currentScore = " +
- (currentNetwork != null ? currentNetwork.getCurrentScore() : 0) +
- ", newScore = " + score);
- }
- if (currentNetwork == null || currentNetwork.getCurrentScore() < score) {
- reassignedRequests.put(nri, newNetwork);
- }
- } else if (newNetwork.isSatisfyingRequest(nri.request.requestId)) {
- reassignedRequests.put(nri, null);
- }
- }
// Find and migrate to this Network any NetworkRequests for
// which this network is now the best.
@@ -6549,66 +6549,43 @@
mLegacyTypeTracker.add(TYPE_VPN, newNetwork);
}
}
- if (reapUnvalidatedNetworks == ReapUnvalidatedNetworks.REAP) {
- for (NetworkAgentInfo nai : mNetworkAgentInfos.values()) {
- if (unneeded(nai, UnneededFor.TEARDOWN)) {
- if (nai.getLingerExpiry() > 0) {
- // This network has active linger timers and no requests, but is not
- // lingering. Linger it.
- //
- // One way (the only way?) this can happen if this network is unvalidated
- // and became unneeded due to another network improving its score to the
- // point where this network will no longer be able to satisfy any requests
- // even if it validates.
- updateLingerState(nai, now);
- } else {
- if (DBG) log("Reaping " + nai.name());
- teardownUnneededNetwork(nai);
- }
- }
- }
- }
}
/**
* Attempt to rematch all Networks with NetworkRequests. This may result in Networks
* being disconnected.
- * @param changed If only one Network's score or capabilities have been modified since the last
- * time this function was called, pass this Network in this argument, otherwise pass
- * null.
- * @param oldScore If only one Network has been changed but its NetworkCapabilities have not
- * changed, pass in the Network's score (from getCurrentScore()) prior to the change via
- * this argument, otherwise pass {@code changed.getCurrentScore()} or 0 if
- * {@code changed} is {@code null}. This is because NetworkCapabilities influence a
- * network's score.
*/
- private void rematchAllNetworksAndRequests(NetworkAgentInfo changed, int oldScore) {
- // TODO: This may get slow. The "changed" parameter is provided for future optimization
- // to avoid the slowness. It is not simply enough to process just "changed", for
- // example in the case where "changed"'s score decreases and another network should begin
- // satisfying a NetworkRequest that "changed" currently satisfies.
-
- // Optimization: Only reprocess "changed" if its score improved. This is safe because it
- // can only add more NetworkRequests satisfied by "changed", and this is exactly what
- // rematchNetworkAndRequests() handles.
+ private void rematchAllNetworksAndRequests() {
+ // TODO: This may be slow, and should be optimized. Unfortunately at this moment the
+ // processing is network-major instead of request-major (the code iterates through all
+ // networks, then for each it iterates for all requests), which is a problem for re-scoring
+ // requests. Once the code has switched to a request-major iteration style, this can
+ // be optimized to only do the processing needed.
final long now = SystemClock.elapsedRealtime();
- if (changed != null && oldScore < changed.getCurrentScore()) {
- rematchNetworkAndRequests(changed, ReapUnvalidatedNetworks.REAP, now);
- } else {
- final NetworkAgentInfo[] nais = mNetworkAgentInfos.values().toArray(
- new NetworkAgentInfo[mNetworkAgentInfos.size()]);
- // Rematch higher scoring networks first to prevent requests first matching a lower
- // scoring network and then a higher scoring network, which could produce multiple
- // callbacks and inadvertently unlinger networks.
- Arrays.sort(nais);
- for (NetworkAgentInfo nai : nais) {
- rematchNetworkAndRequests(nai,
- // Only reap the last time through the loop. Reaping before all rematching
- // is complete could incorrectly teardown a network that hasn't yet been
- // rematched.
- (nai != nais[nais.length-1]) ? ReapUnvalidatedNetworks.DONT_REAP
- : ReapUnvalidatedNetworks.REAP,
- now);
+ final NetworkAgentInfo[] nais = mNetworkAgentInfos.values().toArray(
+ new NetworkAgentInfo[mNetworkAgentInfos.size()]);
+ // Rematch higher scoring networks first to prevent requests first matching a lower
+ // scoring network and then a higher scoring network, which could produce multiple
+ // callbacks and inadvertently unlinger networks.
+ Arrays.sort(nais);
+ for (NetworkAgentInfo nai : nais) {
+ rematchNetworkAndRequests(nai, now);
+ }
+ for (NetworkAgentInfo nai : mNetworkAgentInfos.values()) {
+ if (unneeded(nai, UnneededFor.TEARDOWN)) {
+ if (nai.getLingerExpiry() > 0) {
+ // This network has active linger timers and no requests, but is not
+ // lingering. Linger it.
+ //
+ // One way (the only way?) this can happen if this network is unvalidated
+ // and became unneeded due to another network improving its score to the
+ // point where this network will no longer be able to satisfy any requests
+ // even if it validates.
+ updateLingerState(nai, now);
+ } else {
+ if (DBG) log("Reaping " + nai.name());
+ teardownUnneededNetwork(nai);
+ }
}
}
}
@@ -6707,8 +6684,7 @@
}
// Consider network even though it is not yet validated.
- final long now = SystemClock.elapsedRealtime();
- rematchNetworkAndRequests(networkAgent, ReapUnvalidatedNetworks.REAP, now);
+ rematchAllNetworksAndRequests();
// This has to happen after matching the requests, because callbacks are just requests.
notifyNetworkCallbacks(networkAgent, ConnectivityManager.CALLBACK_PRECHECK);
@@ -6729,7 +6705,7 @@
state == NetworkInfo.State.SUSPENDED)) {
// going into or coming out of SUSPEND: re-score and notify
if (networkAgent.getCurrentScore() != oldScore) {
- rematchAllNetworksAndRequests(networkAgent, oldScore);
+ rematchAllNetworksAndRequests();
}
updateCapabilities(networkAgent.getCurrentScore(), networkAgent,
networkAgent.networkCapabilities);
@@ -6743,19 +6719,9 @@
}
private void updateNetworkScore(NetworkAgentInfo nai, NetworkScore ns) {
- int score = ns.getIntExtension(NetworkScore.LEGACY_SCORE);
- if (VDBG || DDBG) log("updateNetworkScore for " + nai.name() + " to " + score);
- if (score < 0) {
- loge("updateNetworkScore for " + nai.name() + " got a negative score (" + score +
- "). Bumping score to min of 0");
- score = 0;
- }
-
- final int oldScore = nai.getCurrentScore();
+ if (VDBG || DDBG) log("updateNetworkScore for " + nai.name() + " to " + ns);
nai.setNetworkScore(ns);
-
- rematchAllNetworksAndRequests(nai, oldScore);
-
+ rematchAllNetworksAndRequests();
sendUpdatedScoreToFactories(nai);
}
diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java
index 34c5842..9ebe896 100644
--- a/services/core/java/com/android/server/LocationManagerService.java
+++ b/services/core/java/com/android/server/LocationManagerService.java
@@ -3309,18 +3309,24 @@
ipw.decreaseIndent();
}
- mSettingsStore.dump(fd, pw, args);
+ ipw.println("Location Settings:");
+ ipw.increaseIndent();
+ mSettingsStore.dump(fd, ipw, args);
+ ipw.decreaseIndent();
ipw.println("Location Providers:");
ipw.increaseIndent();
for (LocationProvider provider : mProviders) {
provider.dumpLocked(fd, ipw, args);
}
+ ipw.decreaseIndent();
}
if (mGnssManagerService != null) {
+ ipw.println("GNSS:");
+ ipw.increaseIndent();
+ mGnssManagerService.dump(fd, ipw, args);
ipw.decreaseIndent();
- mGnssManagerService.dump(fd, pw, args);
}
}
}
diff --git a/services/core/java/com/android/server/NetworkScoreService.java b/services/core/java/com/android/server/NetworkScoreService.java
index df5005e..b26ef92 100644
--- a/services/core/java/com/android/server/NetworkScoreService.java
+++ b/services/core/java/com/android/server/NetworkScoreService.java
@@ -58,12 +58,10 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.content.PackageMonitor;
-import com.android.internal.os.TransferPipe;
import com.android.internal.util.DumpUtils;
import com.android.server.pm.permission.PermissionManagerServiceInternal;
import java.io.FileDescriptor;
-import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collection;
@@ -903,17 +901,6 @@
}
writer.println("Current scorer: " + currentScorer);
- sendCacheUpdateCallback(new BiConsumer<INetworkScoreCache, Object>() {
- @Override
- public void accept(INetworkScoreCache networkScoreCache, Object cookie) {
- try {
- TransferPipe.dumpAsync(networkScoreCache.asBinder(), fd, args);
- } catch (IOException | RemoteException e) {
- writer.println("Failed to dump score cache: " + e);
- }
- }
- }, getScoreCacheLists());
-
synchronized (mServiceConnectionLock) {
if (mServiceConnection != null) {
mServiceConnection.dump(fd, writer, args);
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index dcc690f..a4bc3bd 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -80,6 +80,7 @@
import android.os.IStoraged;
import android.os.IVold;
import android.os.IVoldListener;
+import android.os.IVoldMountCallback;
import android.os.IVoldTaskListener;
import android.os.Looper;
import android.os.Message;
@@ -348,10 +349,6 @@
@GuardedBy("mLock")
private ArrayMap<String, CountDownLatch> mDiskScanLatches = new ArrayMap<>();
- /** Map from volume ID to latches */
- @GuardedBy("mLock")
- private ArrayMap<String, CountDownLatch> mFuseVolumeReadyLatches = new ArrayMap<>();
-
@GuardedBy("mLock")
private IPackageMoveObserver mMoveCallback;
@GuardedBy("mLock")
@@ -464,17 +461,6 @@
}
}
- private CountDownLatch findOrCreateFuseVolumeReadyLatch(String volId) {
- synchronized (mLock) {
- CountDownLatch latch = mFuseVolumeReadyLatches.get(volId);
- if (latch == null) {
- latch = new CountDownLatch(1);
- mFuseVolumeReadyLatches.put(volId, latch);
- }
- return latch;
- }
- }
-
/** List of crypto types.
* These must match CRYPT_TYPE_XXX in cryptfs.h AND their
* corresponding commands in CommandListener.cpp */
@@ -612,7 +598,6 @@
private static final int H_ABORT_IDLE_MAINT = 12;
private static final int H_BOOT_COMPLETED = 13;
private static final int H_COMPLETE_UNLOCK_USER = 14;
- private static final int H_VOLUME_READY = 15;
class StorageManagerServiceHandler extends Handler {
public StorageManagerServiceHandler(Looper looper) {
@@ -673,22 +658,6 @@
}
break;
}
- case H_VOLUME_READY: {
- final VolumeInfo vol = (VolumeInfo) msg.obj;
- try {
- mStorageSessionController.onVolumeReady(vol);
-
- synchronized (mLock) {
- CountDownLatch latch = mFuseVolumeReadyLatches.remove(vol.id);
- if (latch != null) {
- latch.countDown();
- }
- }
- } catch (IllegalStateException | ExternalStorageServiceException e) {
- Slog.i(TAG, "Failed to initialise volume " + vol, e);
- }
- break;
- }
case H_VOLUME_MOUNT: {
final VolumeInfo vol = (VolumeInfo) msg.obj;
if (isMountDisallowed(vol)) {
@@ -1431,13 +1400,6 @@
writeSettingsLocked();
}
- if (mIsFuseEnabled && newState == VolumeInfo.STATE_MOUNTED
- && (vol.type == VolumeInfo.TYPE_PUBLIC || vol.type == VolumeInfo.TYPE_EMULATED)) {
- Slog.i(TAG, "Initialising volume " + vol + " ...");
- // TODO(b/144275217): Delay broadcasts till mount is really ready
- mHandler.obtainMessage(H_VOLUME_READY, vol).sendToTarget();
- }
-
mCallbacks.notifyVolumeStateChanged(vol, oldState, newState);
// Do not broadcast before boot has completed to avoid launching the
@@ -1912,33 +1874,29 @@
throw new SecurityException("Mounting " + volId + " restricted by policy");
}
- CountDownLatch latch = null;
- if (mIsFuseEnabled && StorageSessionController.isEmulatedOrPublic(vol)) {
- latch = findOrCreateFuseVolumeReadyLatch(volId);
- }
-
mount(vol);
-
- if (latch != null) {
- try {
- waitForLatch(latch, "mount " + volId, 3 * DateUtils.MINUTE_IN_MILLIS);
- } catch (TimeoutException e) {
- Slog.wtf(TAG, e);
- } finally {
- synchronized (mLock) {
- mFuseVolumeReadyLatches.remove(volId);
- }
- }
- }
}
private void mount(VolumeInfo vol) {
try {
// TODO(b/135341433): Remove paranoid logging when FUSE is stable
Slog.i(TAG, "Mounting volume " + vol);
- FileDescriptor fd = mVold.mount(vol.id, vol.mountFlags, vol.mountUserId);
+ mVold.mount(vol.id, vol.mountFlags, vol.mountUserId, new IVoldMountCallback.Stub() {
+ @Override
+ public boolean onVolumeChecking(FileDescriptor deviceFd, String path,
+ String internalPath) {
+ vol.path = path;
+ vol.internalPath = internalPath;
+ try {
+ mStorageSessionController.onVolumeMount(deviceFd, vol);
+ return true;
+ } catch (ExternalStorageServiceException e) {
+ Slog.i(TAG, "Failed to mount volume " + vol, e);
+ return false;
+ }
+ }
+ });
Slog.i(TAG, "Mounted volume " + vol);
- mStorageSessionController.onVolumeMount(fd, vol);
} catch (Exception e) {
Slog.wtf(TAG, e);
}
@@ -2771,11 +2729,6 @@
*/
@Override
public boolean supportsCheckpoint() throws RemoteException {
- // Only the system process is permitted to start checkpoints
- if (Binder.getCallingUid() != android.os.Process.SYSTEM_UID) {
- throw new SecurityException("no permission to check filesystem checkpoint support");
- }
-
return mVold.supportsCheckpoint();
}
@@ -2926,12 +2879,6 @@
enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
if (StorageManager.isFileEncryptedNativeOrEmulated()) {
- // When a user has secure lock screen, require secret to actually unlock.
- // This check is mostly in place for emulation mode.
- if (mLockPatternUtils.isSecure(userId) && ArrayUtils.isEmpty(secret)) {
- throw new IllegalStateException("Secret required to unlock secure user " + userId);
- }
-
try {
mVold.unlockUserKey(userId, serialNumber, encodeBytes(token),
encodeBytes(secret));
@@ -3648,7 +3595,7 @@
try {
mObbState.volId = mVold.createObb(mObbState.canonicalPath, binderKey,
mObbState.ownerGid);
- mVold.mount(mObbState.volId, 0, -1);
+ mVold.mount(mObbState.volId, 0, -1, null);
if (DEBUG_OBB)
Slog.d(TAG, "Successfully mounted OBB " + mObbState.canonicalPath);
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 88d0e4b..5b7a814 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -568,6 +568,11 @@
private static final int NATIVE_DUMP_TIMEOUT_MS = 2000; // 2 seconds;
private static final int JAVA_DUMP_MINIMUM_SIZE = 100; // 100 bytes.
+ /**
+ * How long between a process kill and we actually receive its death recipient
+ */
+ private static final long PROC_KILL_TIMEOUT = 5000; // 5 seconds;
+
OomAdjuster mOomAdjuster;
final LowMemDetector mLowMemDetector;
@@ -3738,6 +3743,9 @@
"Dying app: " + app + ", pid: " + pid + ", thread: " + thread.asBinder());
handleAppDiedLocked(app, false, true);
+ // Execute the callback if there is any.
+ doAppDiedCallbackLocked(app);
+
if (doOomAdj) {
updateOomAdjLocked(OomAdjuster.OOM_ADJ_REASON_PROCESS_END);
}
@@ -3749,6 +3757,10 @@
reportUidInfoMessageLocked(TAG,
"Process " + app.processName + " (pid " + pid
+ ") has died and restarted (pid " + app.pid + ").", app.info.uid);
+
+ // Execute the callback if there is any.
+ doAppDiedCallbackLocked(app);
+
EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.userId, app.pid, app.processName);
} else if (DEBUG_PROCESSES) {
Slog.d(TAG_PROCESSES, "Received spurious death notification for thread "
@@ -3762,6 +3774,39 @@
}
}
+ @GuardedBy("this")
+ private void doAppDiedCallbackLocked(final ProcessRecord app) {
+ if (app.mAppDiedCallback != null) {
+ app.mAppDiedCallback.run();
+ app.mAppDiedCallback = null;
+ }
+ }
+
+ @GuardedBy("this")
+ private void waitForProcKillLocked(final ProcessRecord app, final String formatString,
+ final long startTime) {
+ app.mAppDiedCallback = () -> {
+ synchronized (ActivityManagerService.this) {
+ // called when this app receives appDiedLocked()
+ ActivityManagerService.this.notifyAll();
+ }
+ };
+ checkTime(startTime, String.format(formatString, "before appDied"));
+ long now = SystemClock.uptimeMillis();
+ long timeout = PROC_KILL_TIMEOUT + now;
+ while (app.mAppDiedCallback != null && timeout > now) {
+ try {
+ wait(timeout - now);
+ } catch (InterruptedException e) {
+ }
+ now = SystemClock.uptimeMillis();
+ }
+ checkTime(startTime, String.format(formatString, "after appDied"));
+ if (app.mAppDiedCallback != null) {
+ Slog.w(TAG, String.format(formatString, "waiting for app killing timed out"));
+ }
+ }
+
/**
* If a stack trace dump file is configured, dump process stack traces.
* @param firstPids of dalvik VM processes to dump stack traces for first
@@ -6779,18 +6824,12 @@
// Note if killedByAm is also set, this means the provider process has just been
// killed by AM (in ProcessRecord.kill()), but appDiedLocked() hasn't been called
- // yet. So we need to call appDiedLocked() here and let it clean up.
+ // yet. So we need to wait for appDiedLocked() here and let it clean up.
// (See the commit message on I2c4ba1e87c2d47f2013befff10c49b3dc337a9a7 to see
// how to test this case.)
if (cpr.proc.killed && cpr.proc.killedByAm) {
- checkTime(startTime, "getContentProviderImpl: before appDied (killedByAm)");
- final long iden = Binder.clearCallingIdentity();
- try {
- appDiedLocked(cpr.proc);
- } finally {
- Binder.restoreCallingIdentity(iden);
- }
- checkTime(startTime, "getContentProviderImpl: after appDied (killedByAm)");
+ waitForProcKillLocked(cpr.proc, "getContentProviderImpl: %s (killedByAm)",
+ startTime);
}
}
@@ -6894,9 +6933,7 @@
Slog.i(TAG, "Existing provider " + cpr.name.flattenToShortString()
+ " is crashing; detaching " + r);
boolean lastRef = decProviderCountLocked(conn, cpr, token, stable);
- checkTime(startTime, "getContentProviderImpl: before appDied");
- appDiedLocked(cpr.proc);
- checkTime(startTime, "getContentProviderImpl: after appDied");
+ waitForProcKillLocked(cpr.proc, "getContentProviderImpl: %s", startTime);
if (!lastRef) {
// This wasn't the last ref our process had on
// the provider... we have now been killed, bail.
diff --git a/services/core/java/com/android/server/am/CarUserSwitchingDialog.java b/services/core/java/com/android/server/am/CarUserSwitchingDialog.java
index c7de7b1..183e059 100644
--- a/services/core/java/com/android/server/am/CarUserSwitchingDialog.java
+++ b/services/core/java/com/android/server/am/CarUserSwitchingDialog.java
@@ -37,6 +37,7 @@
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
+
import com.android.internal.R;
@@ -65,7 +66,9 @@
setCancelable(false);
Resources res = getContext().getResources();
// Custom view due to alignment and font size requirements
- getContext().setTheme(R.style.Theme_DeviceDefault_Light_Dialog_Alert_UserSwitchingDialog);
+ // TODO (b/145021634): disabled because it's delaying user switch by 3 seconds
+ // getContext()
+ // .setTheme(R.style.Theme_DeviceDefault_Light_Dialog_Alert_UserSwitchingDialog);
View view = LayoutInflater.from(getContext()).inflate(
R.layout.car_user_switching_dialog,
null);
diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java
index 30674db..0591704 100644
--- a/services/core/java/com/android/server/am/OomAdjuster.java
+++ b/services/core/java/com/android/server/am/OomAdjuster.java
@@ -306,7 +306,7 @@
@GuardedBy("mService")
void updateOomAdjLocked(String oomAdjReason) {
final ProcessRecord topApp = mService.getTopAppLocked();
- updateOomAdjLockedInner(oomAdjReason, topApp , null, null, true);
+ updateOomAdjLockedInner(oomAdjReason, topApp , null, null, true, true);
}
/**
@@ -361,8 +361,10 @@
uids.clear();
queue.clear();
- // borrow the "containsCycle" flag to mark it being scanned
- app.containsCycle = true;
+ // Track if any of them reachables could include a cycle
+ boolean containsCycle = false;
+ // Scan downstreams of the process record
+ app.mReachable = true;
for (ProcessRecord pr = app; pr != null; pr = queue.poll()) {
if (pr != app) {
processes.add(pr);
@@ -374,7 +376,7 @@
ConnectionRecord cr = pr.connections.valueAt(i);
ProcessRecord service = (cr.flags & ServiceInfo.FLAG_ISOLATED_PROCESS) != 0
? cr.binding.service.isolatedProc : cr.binding.service.app;
- if (service == null || service.containsCycle) {
+ if (service == null || service == pr || (containsCycle |= service.mReachable)) {
continue;
}
if ((cr.flags & (Context.BIND_WAIVE_PRIORITY
@@ -384,21 +386,21 @@
continue;
}
queue.offer(service);
- service.containsCycle = true;
+ service.mReachable = true;
}
for (int i = pr.conProviders.size() - 1; i >= 0; i--) {
ContentProviderConnection cpc = pr.conProviders.get(i);
ProcessRecord provider = cpc.provider.proc;
- if (provider == null || provider.containsCycle) {
+ if (provider == null || provider == pr || (containsCycle |= provider.mReachable)) {
continue;
}
queue.offer(provider);
- provider.containsCycle = true;
+ provider.mReachable = true;
}
}
// Reset the flag
- app.containsCycle = false;
+ app.mReachable = false;
int size = processes.size();
if (size > 0) {
// Reverse the process list, since the updateOomAdjLockedInner scans from the end of it.
@@ -409,7 +411,7 @@
}
mAdjSeq--;
// Update these reachable processes
- updateOomAdjLockedInner(oomAdjReason, topApp, processes, uids, false);
+ updateOomAdjLockedInner(oomAdjReason, topApp, processes, uids, containsCycle, false);
} else if (app.getCurRawAdj() == ProcessList.UNKNOWN_ADJ) {
// In case the app goes from non-cached to cached but it doesn't have other reachable
// processes, its adj could be still unknown as of now, assign one.
@@ -430,7 +432,8 @@
*/
@GuardedBy("mService")
private void updateOomAdjLockedInner(String oomAdjReason, final ProcessRecord topApp,
- ArrayList<ProcessRecord> processes, ActiveUids uids, boolean startProfiling) {
+ ArrayList<ProcessRecord> processes, ActiveUids uids, boolean potentialCycles,
+ boolean startProfiling) {
if (startProfiling) {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, oomAdjReason);
mService.mOomAdjProfiler.oomAdjStarted();
@@ -474,11 +477,13 @@
}
boolean retryCycles = false;
+ boolean computeClients = fullUpdate || potentialCycles;
// need to reset cycle state before calling computeOomAdjLocked because of service conns
for (int i = numProc - 1; i >= 0; i--) {
ProcessRecord app = activeProcesses.get(i);
app.containsCycle = false;
+ app.mReachable = false;
app.setCurRawProcState(PROCESS_STATE_CACHED_EMPTY);
app.setCurRawAdj(ProcessList.UNKNOWN_ADJ);
app.setCapability = PROCESS_CAPABILITY_NONE;
@@ -489,7 +494,7 @@
if (!app.killedByAm && app.thread != null) {
app.procStateChanged = false;
computeOomAdjLocked(app, ProcessList.UNKNOWN_ADJ, topApp, fullUpdate, now, false,
- fullUpdate); // It won't enter cycle if not computing clients.
+ computeClients); // It won't enter cycle if not computing clients.
// if any app encountered a cycle, we need to perform an additional loop later
retryCycles |= app.containsCycle;
// Keep the completedAdjSeq to up to date.
@@ -499,7 +504,7 @@
assignCachedAdjIfNecessary(mProcessList.mLruProcesses);
- if (fullUpdate) { // There won't be cycles if we didn't compute clients above.
+ if (computeClients) { // There won't be cycles if we didn't compute clients above.
// Cycle strategy:
// - Retry computing any process that has encountered a cycle.
// - Continue retrying until no process was promoted.
diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java
index 1e0693f..867571a 100644
--- a/services/core/java/com/android/server/am/ProcessRecord.java
+++ b/services/core/java/com/android/server/am/ProcessRecord.java
@@ -327,6 +327,11 @@
int mCachedProcState = ActivityManager.PROCESS_STATE_CACHED_EMPTY;
int mCachedSchedGroup = ProcessList.SCHED_GROUP_BACKGROUND;
+ boolean mReachable; // Whether or not this process is reachable from given process
+
+ // A callback that should be executed on app died; after that it'll be set to null
+ Runnable mAppDiedCallback;
+
void setStartParams(int startUid, HostingRecord hostingRecord, String seInfo,
long startTime) {
this.startUid = startUid;
diff --git a/services/core/java/com/android/server/audio/AudioDeviceInventory.java b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
index 90973a8..a2b3574 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceInventory.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
@@ -44,6 +44,8 @@
import com.android.internal.annotations.VisibleForTesting;
import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Set;
/**
* Class to manage the inventory of all connected devices.
@@ -372,9 +374,14 @@
mDeviceBroker.postObserveDevicesForAllStreams();
}
- private static final int DEVICE_OVERRIDE_A2DP_ROUTE_ON_PLUG =
- AudioSystem.DEVICE_OUT_WIRED_HEADSET | AudioSystem.DEVICE_OUT_WIRED_HEADPHONE
- | AudioSystem.DEVICE_OUT_LINE | AudioSystem.DEVICE_OUT_ALL_USB;
+ private static final Set<Integer> DEVICE_OVERRIDE_A2DP_ROUTE_ON_PLUG_SET;
+ static {
+ DEVICE_OVERRIDE_A2DP_ROUTE_ON_PLUG_SET = new HashSet<>();
+ DEVICE_OVERRIDE_A2DP_ROUTE_ON_PLUG_SET.add(AudioSystem.DEVICE_OUT_WIRED_HEADSET);
+ DEVICE_OVERRIDE_A2DP_ROUTE_ON_PLUG_SET.add(AudioSystem.DEVICE_OUT_WIRED_HEADPHONE);
+ DEVICE_OVERRIDE_A2DP_ROUTE_ON_PLUG_SET.add(AudioSystem.DEVICE_OUT_LINE);
+ DEVICE_OVERRIDE_A2DP_ROUTE_ON_PLUG_SET.addAll(AudioSystem.DEVICE_OUT_ALL_USB_SET);
+ }
/*package*/ void onSetWiredDeviceConnectionState(
AudioDeviceInventory.WiredDeviceConnectionState wdcs) {
@@ -382,7 +389,7 @@
synchronized (mConnectedDevices) {
if ((wdcs.mState == AudioService.CONNECTION_STATE_DISCONNECTED)
- && ((wdcs.mType & DEVICE_OVERRIDE_A2DP_ROUTE_ON_PLUG) != 0)) {
+ && DEVICE_OVERRIDE_A2DP_ROUTE_ON_PLUG_SET.contains(wdcs.mType)) {
mDeviceBroker.setBluetoothA2dpOnInt(true,
"onSetWiredDeviceConnectionState state DISCONNECTED");
}
@@ -393,7 +400,7 @@
return;
}
if (wdcs.mState != AudioService.CONNECTION_STATE_DISCONNECTED) {
- if ((wdcs.mType & DEVICE_OVERRIDE_A2DP_ROUTE_ON_PLUG) != 0) {
+ if (DEVICE_OVERRIDE_A2DP_ROUTE_ON_PLUG_SET.contains(wdcs.mType)) {
mDeviceBroker.setBluetoothA2dpOnInt(false,
"onSetWiredDeviceConnectionState state not DISCONNECTED");
}
@@ -764,13 +771,19 @@
// - none of these devices are connected anymore after one is disconnected AND
// - the device being disconnected is actually used for music.
// Access synchronized on mConnectedDevices
- private int mBecomingNoisyIntentDevices =
- AudioSystem.DEVICE_OUT_WIRED_HEADSET | AudioSystem.DEVICE_OUT_WIRED_HEADPHONE
- | AudioSystem.DEVICE_OUT_ALL_A2DP | AudioSystem.DEVICE_OUT_HDMI
- | AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET
- | AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET
- | AudioSystem.DEVICE_OUT_ALL_USB | AudioSystem.DEVICE_OUT_LINE
- | AudioSystem.DEVICE_OUT_HEARING_AID;
+ private static final Set<Integer> BECOMING_NOISY_INTENT_DEVICES_SET;
+ static {
+ BECOMING_NOISY_INTENT_DEVICES_SET = new HashSet<>();
+ BECOMING_NOISY_INTENT_DEVICES_SET.add(AudioSystem.DEVICE_OUT_WIRED_HEADSET);
+ BECOMING_NOISY_INTENT_DEVICES_SET.add(AudioSystem.DEVICE_OUT_WIRED_HEADPHONE);
+ BECOMING_NOISY_INTENT_DEVICES_SET.add(AudioSystem.DEVICE_OUT_HDMI);
+ BECOMING_NOISY_INTENT_DEVICES_SET.add(AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET);
+ BECOMING_NOISY_INTENT_DEVICES_SET.add(AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET);
+ BECOMING_NOISY_INTENT_DEVICES_SET.add(AudioSystem.DEVICE_OUT_LINE);
+ BECOMING_NOISY_INTENT_DEVICES_SET.add(AudioSystem.DEVICE_OUT_HEARING_AID);
+ BECOMING_NOISY_INTENT_DEVICES_SET.addAll(AudioSystem.DEVICE_OUT_ALL_A2DP_SET);
+ BECOMING_NOISY_INTENT_DEVICES_SET.addAll(AudioSystem.DEVICE_OUT_ALL_USB_SET);
+ }
// must be called before removing the device from mConnectedDevices
// musicDevice argument is used when not AudioSystem.DEVICE_NONE instead of querying
@@ -781,16 +794,16 @@
if (state != AudioService.CONNECTION_STATE_DISCONNECTED) {
return 0;
}
- if ((device & mBecomingNoisyIntentDevices) == 0) {
+ if (!BECOMING_NOISY_INTENT_DEVICES_SET.contains(device)) {
return 0;
}
int delay = 0;
- int devices = 0;
+ Set<Integer> devices = new HashSet<>();
for (int i = 0; i < mConnectedDevices.size(); i++) {
int dev = mConnectedDevices.valueAt(i).mDeviceType;
if (((dev & AudioSystem.DEVICE_BIT_IN) == 0)
- && ((dev & mBecomingNoisyIntentDevices) != 0)) {
- devices |= dev;
+ && BECOMING_NOISY_INTENT_DEVICES_SET.contains(dev)) {
+ devices.add(dev);
}
}
if (musicDevice == AudioSystem.DEVICE_NONE) {
@@ -801,8 +814,9 @@
// because music routing is altered in this case.
// also checks whether media routing if affected by a dynamic policy or mirroring
if (((device == musicDevice) || mDeviceBroker.isInCommunication())
- && (device == devices) && !mDeviceBroker.hasMediaDynamicPolicy()
- && ((musicDevice & AudioSystem.DEVICE_OUT_REMOTE_SUBMIX) == 0)) {
+ && AudioSystem.isSingleAudioDeviceType(devices, device)
+ && !mDeviceBroker.hasMediaDynamicPolicy()
+ && (musicDevice != AudioSystem.DEVICE_OUT_REMOTE_SUBMIX)) {
if (!AudioSystem.isStreamActive(AudioSystem.STREAM_MUSIC, 0 /*not looking in past*/)
&& !mDeviceBroker.hasAudioFocusUsers()) {
// no media playback, not a "becoming noisy" situation, otherwise it could cause
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 9a92778..e426c6c 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -147,6 +147,7 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
@@ -501,18 +502,20 @@
private volatile IRingtonePlayer mRingtonePlayer;
// Devices for which the volume is fixed (volume is either max or muted)
- int mFixedVolumeDevices = AudioSystem.DEVICE_OUT_HDMI |
- AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET |
- AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET |
- AudioSystem.DEVICE_OUT_HDMI_ARC |
- AudioSystem.DEVICE_OUT_SPDIF |
- AudioSystem.DEVICE_OUT_AUX_LINE;
+ Set<Integer> mFixedVolumeDevices = new HashSet<>(Arrays.asList(
+ AudioSystem.DEVICE_OUT_HDMI,
+ AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET,
+ AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET,
+ AudioSystem.DEVICE_OUT_HDMI_ARC,
+ AudioSystem.DEVICE_OUT_SPDIF,
+ AudioSystem.DEVICE_OUT_AUX_LINE));
// Devices for which the volume is always max, no volume panel
- int mFullVolumeDevices = 0;
+ Set<Integer> mFullVolumeDevices = new HashSet<>();
// Devices for the which use the "absolute volume" concept (framework sends audio signal
// full scale, and volume control separately) and can be used for multiple use cases reflected
// by the audio mode (e.g. media playback in MODE_NORMAL, and phone calls in MODE_IN_CALL).
- int mAbsVolumeMultiModeCaseDevices = AudioSystem.DEVICE_OUT_HEARING_AID;
+ Set<Integer> mAbsVolumeMultiModeCaseDevices = new HashSet<>(
+ Arrays.asList(AudioSystem.DEVICE_OUT_HEARING_AID));
private final boolean mMonitorRotation;
@@ -866,13 +869,14 @@
}
mHdmiTvClient = mHdmiManager.getTvClient();
if (mHdmiTvClient != null) {
- mFixedVolumeDevices &= ~AudioSystem.DEVICE_ALL_HDMI_SYSTEM_AUDIO_AND_SPEAKER;
+ mFixedVolumeDevices.removeAll(
+ AudioSystem.DEVICE_ALL_HDMI_SYSTEM_AUDIO_AND_SPEAKER_SET);
}
mHdmiPlaybackClient = mHdmiManager.getPlaybackClient();
if (mHdmiPlaybackClient != null) {
// not a television: HDMI output will be always at max
- mFixedVolumeDevices &= ~AudioSystem.DEVICE_OUT_HDMI;
- mFullVolumeDevices |= AudioSystem.DEVICE_OUT_HDMI;
+ mFixedVolumeDevices.remove(AudioSystem.DEVICE_OUT_HDMI);
+ mFullVolumeDevices.add(AudioSystem.DEVICE_OUT_HDMI);
}
mHdmiAudioSystemClient = mHdmiManager.getAudioSystemClient();
}
@@ -1131,7 +1135,7 @@
@AudioService.ConnectionState int state, String caller) {
if (state == AudioService.CONNECTION_STATE_CONNECTED) {
// DEVICE_OUT_HDMI is now connected
- if ((AudioSystem.DEVICE_OUT_HDMI & mSafeMediaVolumeDevices) != 0) {
+ if (mSafeMediaVolumeDevices.contains(AudioSystem.DEVICE_OUT_HDMI)) {
sendMsg(mAudioHandler,
MSG_CHECK_MUSIC_ACTIVE,
SENDMSG_REPLACE,
@@ -1762,8 +1766,8 @@
// skip a2dp absolute volume control request when the device
// is not an a2dp device
- if ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) == 0 &&
- (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) != 0) {
+ if (!AudioSystem.DEVICE_OUT_ALL_A2DP_SET.contains(device)
+ && (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) != 0) {
return;
}
@@ -1784,14 +1788,14 @@
flags &= ~AudioManager.FLAG_FIXED_VOLUME;
if ((streamTypeAlias == AudioSystem.STREAM_MUSIC) &&
- ((device & mFixedVolumeDevices) != 0)) {
+ mFixedVolumeDevices.contains(device)) {
flags |= AudioManager.FLAG_FIXED_VOLUME;
// Always toggle between max safe volume and 0 for fixed volume devices where safe
// volume is enforced, and max and 0 for the others.
// This is simulated by stepping by the full allowed volume range
if (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE &&
- (device & mSafeMediaVolumeDevices) != 0) {
+ mSafeMediaVolumeDevices.contains(device)) {
step = safeMediaVolumeIndex(device);
} else {
step = streamState.getMaxIndex();
@@ -1861,7 +1865,7 @@
!checkSafeMediaVolume(streamTypeAlias, aliasIndex + step, device)) {
Log.e(TAG, "adjustStreamVolume() safe volume index = " + oldIndex);
mVolumeController.postDisplaySafeVolumeWarning(flags);
- } else if (((device & mFullVolumeDevices) == 0)
+ } else if (!mFullVolumeDevices.contains(device)
&& (streamState.adjustIndex(direction * step, device, caller)
|| streamState.mIsMuted)) {
// Post message to set system volume (it in turn will post a
@@ -1890,9 +1894,9 @@
int newIndex = mStreamStates[streamType].getIndex(device);
// Check if volume update should be send to AVRCP
- if (streamTypeAlias == AudioSystem.STREAM_MUSIC &&
- (device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0 &&
- (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) == 0) {
+ if (streamTypeAlias == AudioSystem.STREAM_MUSIC
+ && AudioSystem.DEVICE_OUT_ALL_A2DP_SET.contains(device)
+ && (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) == 0) {
if (DEBUG_VOL) {
Log.d(TAG, "adjustSreamVolume: postSetAvrcpAbsoluteVolumeIndex index="
+ newIndex + "stream=" + streamType);
@@ -1901,7 +1905,7 @@
}
// Check if volume update should be send to Hearing Aid
- if ((device & AudioSystem.DEVICE_OUT_HEARING_AID) != 0) {
+ if (device == AudioSystem.DEVICE_OUT_HEARING_AID) {
// only modify the hearing aid attenuation when the stream to modify matches
// the one expected by the hearing aid
if (streamType == getHearingAidStreamType()) {
@@ -1923,7 +1927,7 @@
if (mHdmiCecSink
&& streamTypeAlias == AudioSystem.STREAM_MUSIC
// vol change on a full volume device
- && ((device & mFullVolumeDevices) != 0)) {
+ && mFullVolumeDevices.contains(device)) {
int keyCode = KeyEvent.KEYCODE_UNKNOWN;
switch (direction) {
case AudioManager.ADJUST_RAISE:
@@ -2291,13 +2295,17 @@
int streamType = getHearingAidStreamType(newMode);
- final int device = AudioSystem.getDevicesForStream(streamType);
- if ((device & mAbsVolumeMultiModeCaseDevices) == 0) {
+ final Set<Integer> deviceTypes = AudioSystem.generateAudioDeviceTypesSet(
+ AudioSystem.getDevicesForStream(streamType));
+ final Set<Integer> absVolumeMultiModeCaseDevices = AudioSystem.intersectionAudioDeviceTypes(
+ mAbsVolumeMultiModeCaseDevices, deviceTypes);
+ if (absVolumeMultiModeCaseDevices.isEmpty()) {
return;
}
// handling of specific interfaces goes here:
- if ((device & mAbsVolumeMultiModeCaseDevices) == AudioSystem.DEVICE_OUT_HEARING_AID) {
+ if (AudioSystem.isSingleAudioDeviceType(
+ absVolumeMultiModeCaseDevices, AudioSystem.DEVICE_OUT_HEARING_AID)) {
final int index = getStreamVolume(streamType);
sVolumeLogger.log(new VolumeEvent(VolumeEvent.VOL_MODE_CHANGE_HEARING_AID,
newMode, streamType, index));
@@ -2324,8 +2332,8 @@
// skip a2dp absolute volume control request when the device
// is not an a2dp device
- if ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) == 0 &&
- (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) != 0) {
+ if (!AudioSystem.DEVICE_OUT_ALL_A2DP_SET.contains(device)
+ && (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) != 0) {
return;
}
// If we are being called by the system (e.g. hardware keys) check for current user
@@ -2357,7 +2365,7 @@
index = rescaleIndex(index * 10, streamType, streamTypeAlias);
if (streamTypeAlias == AudioSystem.STREAM_MUSIC
- && (device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0
+ && AudioSystem.DEVICE_OUT_ALL_A2DP_SET.contains(device)
&& (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) == 0) {
if (DEBUG_VOL) {
Log.d(TAG, "setStreamVolume postSetAvrcpAbsoluteVolumeIndex index=" + index
@@ -2366,7 +2374,7 @@
mDeviceBroker.postSetAvrcpAbsoluteVolumeIndex(index / 10);
}
- if ((device & AudioSystem.DEVICE_OUT_HEARING_AID) != 0
+ if (device == AudioSystem.DEVICE_OUT_HEARING_AID
&& streamType == getHearingAidStreamType()) {
Log.i(TAG, "setStreamVolume postSetHearingAidVolumeIndex index=" + index
+ " stream=" + streamType);
@@ -2379,13 +2387,13 @@
flags &= ~AudioManager.FLAG_FIXED_VOLUME;
if ((streamTypeAlias == AudioSystem.STREAM_MUSIC) &&
- ((device & mFixedVolumeDevices) != 0)) {
+ mFixedVolumeDevices.contains(device)) {
flags |= AudioManager.FLAG_FIXED_VOLUME;
// volume is either 0 or max allowed for fixed volume devices
if (index != 0) {
if (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE &&
- (device & mSafeMediaVolumeDevices) != 0) {
+ mSafeMediaVolumeDevices.contains(device)) {
index = safeMediaVolumeIndex(device);
} else {
index = streamState.getMaxIndex();
@@ -2568,7 +2576,7 @@
if (streamType == AudioSystem.STREAM_MUSIC) {
flags = updateFlagsForTvPlatform(flags);
- if ((device & mFullVolumeDevices) != 0) {
+ if (mFullVolumeDevices.contains(device)) {
flags &= ~AudioManager.FLAG_SHOW_UI;
}
}
@@ -2614,7 +2622,7 @@
int device,
boolean force,
String caller) {
- if ((device & mFullVolumeDevices) != 0) {
+ if (mFullVolumeDevices.contains(device)) {
return;
}
VolumeStreamState streamState = mStreamStates[streamType];
@@ -2731,8 +2739,8 @@
if (!hasRmtSbmxFullVolDeathHandlerFor(cb)) {
mRmtSbmxFullVolDeathHandlers.add(new RmtSbmxFullVolDeathHandler(cb));
if (mRmtSbmxFullVolRefCount == 0) {
- mFullVolumeDevices |= AudioSystem.DEVICE_OUT_REMOTE_SUBMIX;
- mFixedVolumeDevices |= AudioSystem.DEVICE_OUT_REMOTE_SUBMIX;
+ mFullVolumeDevices.add(AudioSystem.DEVICE_OUT_REMOTE_SUBMIX);
+ mFixedVolumeDevices.add(AudioSystem.DEVICE_OUT_REMOTE_SUBMIX);
applyRequired = true;
}
mRmtSbmxFullVolRefCount++;
@@ -2741,8 +2749,8 @@
if (discardRmtSbmxFullVolDeathHandlerFor(cb) && (mRmtSbmxFullVolRefCount > 0)) {
mRmtSbmxFullVolRefCount--;
if (mRmtSbmxFullVolRefCount == 0) {
- mFullVolumeDevices &= ~AudioSystem.DEVICE_OUT_REMOTE_SUBMIX;
- mFixedVolumeDevices &= ~AudioSystem.DEVICE_OUT_REMOTE_SUBMIX;
+ mFullVolumeDevices.remove(AudioSystem.DEVICE_OUT_REMOTE_SUBMIX);
+ mFixedVolumeDevices.remove(AudioSystem.DEVICE_OUT_REMOTE_SUBMIX);
applyRequired = true;
}
}
@@ -2824,7 +2832,7 @@
index = 0;
}
if (index != 0 && (mStreamVolumeAlias[streamType] == AudioSystem.STREAM_MUSIC) &&
- (device & mFixedVolumeDevices) != 0) {
+ mFixedVolumeDevices.contains(device)) {
index = mStreamStates[streamType].getMaxIndex();
}
return (index + 5) / 10;
@@ -3699,7 +3707,7 @@
if (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_INACTIVE) {
int device = getDeviceForStream(AudioSystem.STREAM_MUSIC);
- if ((device & mSafeMediaVolumeDevices) != 0) {
+ if (mSafeMediaVolumeDevices.contains(device)) {
sendMsg(mAudioHandler,
MSG_CHECK_MUSIC_ACTIVE,
SENDMSG_REPLACE,
@@ -4251,6 +4259,8 @@
// retain the device on the A2DP output as the other must not correspond to an active
// selection if not the speaker.
// - HDMI-CEC system audio mode only output: give priority to available item in order.
+ // FIXME: Haven't applied audio device type refactor to this API
+ // as it is going to be deprecated.
if ((device & AudioSystem.DEVICE_OUT_SPEAKER) != 0) {
device = AudioSystem.DEVICE_OUT_SPEAKER;
} else if ((device & AudioSystem.DEVICE_OUT_HDMI_ARC) != 0) {
@@ -4260,7 +4270,11 @@
} else if ((device & AudioSystem.DEVICE_OUT_AUX_LINE) != 0) {
device = AudioSystem.DEVICE_OUT_AUX_LINE;
} else {
- device &= AudioSystem.DEVICE_OUT_ALL_A2DP;
+ for (int deviceType : AudioSystem.DEVICE_OUT_ALL_A2DP_SET) {
+ if ((deviceType & device) == deviceType) {
+ return deviceType;
+ }
+ }
}
}
return device;
@@ -4393,12 +4407,16 @@
mDeviceBroker.postBluetoothA2dpDeviceConfigChange(device);
}
- private static final int DEVICE_MEDIA_UNMUTED_ON_PLUG =
- AudioSystem.DEVICE_OUT_WIRED_HEADSET | AudioSystem.DEVICE_OUT_WIRED_HEADPHONE |
- AudioSystem.DEVICE_OUT_LINE |
- AudioSystem.DEVICE_OUT_ALL_A2DP |
- AudioSystem.DEVICE_OUT_ALL_USB |
- AudioSystem.DEVICE_OUT_HDMI;
+ private static final Set<Integer> DEVICE_MEDIA_UNMUTED_ON_PLUG_SET;
+ static {
+ DEVICE_MEDIA_UNMUTED_ON_PLUG_SET = new HashSet<>();
+ DEVICE_MEDIA_UNMUTED_ON_PLUG_SET.add(AudioSystem.DEVICE_OUT_WIRED_HEADSET);
+ DEVICE_MEDIA_UNMUTED_ON_PLUG_SET.add(AudioSystem.DEVICE_OUT_WIRED_HEADPHONE);
+ DEVICE_MEDIA_UNMUTED_ON_PLUG_SET.add(AudioSystem.DEVICE_OUT_LINE);
+ DEVICE_MEDIA_UNMUTED_ON_PLUG_SET.addAll(AudioSystem.DEVICE_OUT_ALL_A2DP_SET);
+ DEVICE_MEDIA_UNMUTED_ON_PLUG_SET.addAll(AudioSystem.DEVICE_OUT_ALL_USB_SET);
+ DEVICE_MEDIA_UNMUTED_ON_PLUG_SET.add(AudioSystem.DEVICE_OUT_HDMI);
+ }
/** only public for mocking/spying, do not call outside of AudioService */
@VisibleForTesting
@@ -4414,7 +4432,7 @@
}
if (mNm.getZenMode() != Settings.Global.ZEN_MODE_NO_INTERRUPTIONS
- && (newDevice & DEVICE_MEDIA_UNMUTED_ON_PLUG) != 0
+ && DEVICE_MEDIA_UNMUTED_ON_PLUG_SET.contains(newDevice)
&& mStreamStates[AudioSystem.STREAM_MUSIC].mIsMuted
&& mStreamStates[AudioSystem.STREAM_MUSIC].getIndex(newDevice) != 0
&& (newDevice & AudioSystem.getDevicesForStream(AudioSystem.STREAM_MUSIC)) != 0) {
@@ -4543,14 +4561,7 @@
}
}
synchronized (VolumeStreamState.class) {
- int remainingDevices = AudioSystem.DEVICE_OUT_ALL;
-
- for (int i = 0; remainingDevices != 0; i++) {
- int device = (1 << i);
- if ((device & remainingDevices) == 0) {
- continue;
- }
- remainingDevices &= ~device;
+ for (int device : AudioSystem.DEVICE_OUT_ALL_SET) {
// retrieve current volume for device
// if no volume stored for current stream and device, use default volume if default
@@ -4610,11 +4621,12 @@
int index;
if (mIsMuted) {
index = 0;
- } else if ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0 && isAvrcpAbsVolSupported) {
+ } else if (AudioSystem.DEVICE_OUT_ALL_A2DP_SET.contains(device)
+ && isAvrcpAbsVolSupported) {
index = getAbsoluteVolumeIndex((getIndex(device) + 5)/10);
- } else if ((device & mFullVolumeDevices) != 0) {
+ } else if (mFullVolumeDevices.contains(device)) {
index = (mIndexMax + 5)/10;
- } else if ((device & AudioSystem.DEVICE_OUT_HEARING_AID) != 0) {
+ } else if (device == AudioSystem.DEVICE_OUT_HEARING_AID) {
index = (mIndexMax + 5)/10;
} else {
index = (getIndex(device) + 5)/10;
@@ -4632,12 +4644,12 @@
if (device != AudioSystem.DEVICE_OUT_DEFAULT) {
if (mIsMuted) {
index = 0;
- } else if ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0 &&
- isAvrcpAbsVolSupported) {
+ } else if (AudioSystem.DEVICE_OUT_ALL_A2DP_SET.contains(device)
+ && isAvrcpAbsVolSupported) {
index = getAbsoluteVolumeIndex((getIndex(device) + 5)/10);
- } else if ((device & mFullVolumeDevices) != 0) {
+ } else if (mFullVolumeDevices.contains(device)) {
index = (mIndexMax + 5)/10;
- } else if ((device & AudioSystem.DEVICE_OUT_HEARING_AID) != 0) {
+ } else if (device == AudioSystem.DEVICE_OUT_HEARING_AID) {
index = (mIndexMax + 5)/10;
} else {
index = (mIndexMap.valueAt(i) + 5)/10;
@@ -4698,7 +4710,7 @@
&& device == AudioSystem.DEVICE_OUT_SPEAKER) {
for (int i = 0; i < mIndexMap.size(); i++) {
int otherDevice = mIndexMap.keyAt(i);
- if ((otherDevice & AudioSystem.DEVICE_OUT_ALL_SCO) != 0) {
+ if (AudioSystem.DEVICE_OUT_ALL_SCO_SET.contains(otherDevice)) {
mIndexMap.put(otherDevice, index);
}
}
@@ -4836,8 +4848,8 @@
for (int i = 0; i < mIndexMap.size(); i++) {
int device = mIndexMap.keyAt(i);
int index = mIndexMap.valueAt(i);
- if (((device & mFullVolumeDevices) != 0)
- || (((device & mFixedVolumeDevices) != 0) && index != 0)) {
+ if (mFullVolumeDevices.contains(device)
+ || (mFixedVolumeDevices.contains(device) && index != 0)) {
mIndexMap.put(device, mIndexMax);
}
applyDeviceVolume_syncVSS(device, isAvrcpAbsVolSupported);
@@ -5008,7 +5020,7 @@
// that may have a different device selected
int streamDevice = getDeviceForStream(streamType);
if ((device != streamDevice) && isAvrcpAbsVolSupported
- && ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0)) {
+ && AudioSystem.DEVICE_OUT_ALL_A2DP_SET.contains(device)) {
mStreamStates[streamType].applyDeviceVolume_syncVSS(device,
isAvrcpAbsVolSupported);
}
@@ -5337,7 +5349,7 @@
}
/*package*/ void checkMusicActive(int deviceType, String caller) {
- if ((deviceType & mSafeMediaVolumeDevices) != 0) {
+ if (mSafeMediaVolumeDevices.contains(deviceType)) {
sendMsg(mAudioHandler,
MSG_CHECK_MUSIC_ACTIVE,
SENDMSG_REPLACE,
@@ -5783,9 +5795,9 @@
// the headset is compliant to EN 60950 with a max loudness of 100dB SPL.
private int mSafeUsbMediaVolumeIndex;
// mSafeMediaVolumeDevices lists the devices for which safe media volume is enforced,
- /*package*/ final int mSafeMediaVolumeDevices = AudioSystem.DEVICE_OUT_WIRED_HEADSET
- | AudioSystem.DEVICE_OUT_WIRED_HEADPHONE
- | AudioSystem.DEVICE_OUT_USB_HEADSET;
+ /*package*/ final Set<Integer> mSafeMediaVolumeDevices = new HashSet<>(
+ Arrays.asList(AudioSystem.DEVICE_OUT_WIRED_HEADSET,
+ AudioSystem.DEVICE_OUT_WIRED_HEADPHONE, AudioSystem.DEVICE_OUT_USB_HEADSET));
// mMusicActiveMs is the cumulative time of music activity since safe volume was disabled.
// When this time reaches UNSAFE_VOLUME_MUSIC_ACTIVE_MS_MAX, the safe media volume is re-enabled
// automatically. mMusicActiveMs is rounded to a multiple of MUSIC_ACTIVE_POLL_PERIOD_MS.
@@ -5795,7 +5807,7 @@
private static final int SAFE_VOLUME_CONFIGURE_TIMEOUT_MS = 30000; // 30s after boot completed
private int safeMediaVolumeIndex(int device) {
- if ((device & mSafeMediaVolumeDevices) == 0) {
+ if (!mSafeMediaVolumeDevices.contains(device)) {
return MAX_STREAM_VOLUME[AudioSystem.STREAM_MUSIC];
}
if (device == AudioSystem.DEVICE_OUT_USB_HEADSET) {
@@ -5830,14 +5842,9 @@
private void enforceSafeMediaVolume(String caller) {
VolumeStreamState streamState = mStreamStates[AudioSystem.STREAM_MUSIC];
- int devices = mSafeMediaVolumeDevices;
- int i = 0;
+ Set<Integer> devices = mSafeMediaVolumeDevices;
- while (devices != 0) {
- int device = 1 << i++;
- if ((device & devices) == 0) {
- continue;
- }
+ for (int device : devices) {
int index = streamState.getIndex(device);
if (index > safeMediaVolumeIndex(device)) {
streamState.setIndex(safeMediaVolumeIndex(device), device, caller);
@@ -5849,16 +5856,15 @@
streamState,
0);
}
- devices &= ~device;
}
}
private boolean checkSafeMediaVolume(int streamType, int index, int device) {
synchronized (mSafeMediaVolumeStateLock) {
- if ((mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE) &&
- (mStreamVolumeAlias[streamType] == AudioSystem.STREAM_MUSIC) &&
- ((device & mSafeMediaVolumeDevices) != 0) &&
- (index > safeMediaVolumeIndex(device))) {
+ if ((mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE)
+ && (mStreamVolumeAlias[streamType] == AudioSystem.STREAM_MUSIC)
+ && (mSafeMediaVolumeDevices.contains(device))
+ && (index > safeMediaVolumeIndex(device))) {
return false;
}
return true;
@@ -5899,14 +5905,14 @@
if (DEBUG_VOL) {
Log.d(TAG, "CEC sink: setting HDMI as full vol device");
}
- mFullVolumeDevices |= AudioSystem.DEVICE_OUT_HDMI;
+ mFullVolumeDevices.add(AudioSystem.DEVICE_OUT_HDMI);
} else {
if (DEBUG_VOL) {
Log.d(TAG, "TV, no CEC: setting HDMI as regular vol device");
}
// Android TV devices without CEC service apply software volume on
// HDMI output
- mFullVolumeDevices &= ~AudioSystem.DEVICE_OUT_HDMI;
+ mFullVolumeDevices.remove(AudioSystem.DEVICE_OUT_HDMI);
}
checkAddAllFixedVolumeDevices(AudioSystem.DEVICE_OUT_HDMI,
@@ -6127,6 +6133,19 @@
pw.println();
}
+ private String dumpDeviceTypes(@NonNull Set<Integer> deviceTypes) {
+ Iterator<Integer> it = deviceTypes.iterator();
+ if (!it.hasNext()) {
+ return "";
+ }
+ final StringBuilder sb = new StringBuilder();
+ sb.append("0x" + Integer.toHexString(it.next()));
+ while (it.hasNext()) {
+ sb.append("," + "0x" + Integer.toHexString(it.next()));
+ }
+ return sb.toString();
+ }
+
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
@@ -6163,7 +6182,7 @@
pw.println(mDeviceBroker.isAvrcpAbsoluteVolumeSupported());
pw.print(" mIsSingleVolume="); pw.println(mIsSingleVolume);
pw.print(" mUseFixedVolume="); pw.println(mUseFixedVolume);
- pw.print(" mFixedVolumeDevices=0x"); pw.println(Integer.toHexString(mFixedVolumeDevices));
+ pw.print(" mFixedVolumeDevices="); pw.println(dumpDeviceTypes(mFixedVolumeDevices));
pw.print(" mHdmiCecSink="); pw.println(mHdmiCecSink);
pw.print(" mHdmiAudioSystemClient="); pw.println(mHdmiAudioSystemClient);
pw.print(" mHdmiPlaybackClient="); pw.println(mHdmiPlaybackClient);
diff --git a/services/core/java/com/android/server/compat/PlatformCompat.java b/services/core/java/com/android/server/compat/PlatformCompat.java
index ae5ad7e..311e24f 100644
--- a/services/core/java/com/android/server/compat/PlatformCompat.java
+++ b/services/core/java/com/android/server/compat/PlatformCompat.java
@@ -20,7 +20,7 @@
import android.app.IActivityManager;
import android.content.Context;
import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
+import android.content.pm.PackageManagerInternal;
import android.os.Binder;
import android.os.RemoteException;
import android.os.UserHandle;
@@ -32,6 +32,7 @@
import com.android.internal.compat.CompatibilityChangeInfo;
import com.android.internal.compat.IPlatformCompat;
import com.android.internal.util.DumpUtils;
+import com.android.server.LocalServices;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -197,12 +198,8 @@
}
private ApplicationInfo getApplicationInfo(String packageName, int userId) {
- try {
- return mContext.getPackageManager().getApplicationInfoAsUser(packageName, 0, userId);
- } catch (PackageManager.NameNotFoundException e) {
- Slog.e(TAG, "No installed package " + packageName);
- }
- return null;
+ return LocalServices.getService(PackageManagerInternal.class).getApplicationInfo(
+ packageName, 0, userId, userId);
}
private void reportChange(long changeId, int uid, int state) {
@@ -210,11 +207,11 @@
}
private void killPackage(String packageName) {
- int uid = -1;
- try {
- uid = mContext.getPackageManager().getPackageUid(packageName, 0);
- } catch (PackageManager.NameNotFoundException e) {
- Slog.w(TAG, "Didn't find package " + packageName + " on device.", e);
+ int uid = LocalServices.getService(PackageManagerInternal.class).getPackageUid(packageName,
+ 0, UserHandle.myUserId());
+
+ if (uid < 0) {
+ Slog.w(TAG, "Didn't find package " + packageName + " on device.");
return;
}
diff --git a/services/core/java/com/android/server/lights/LightsService.java b/services/core/java/com/android/server/lights/LightsService.java
index ac906bb..eaae2ed 100644
--- a/services/core/java/com/android/server/lights/LightsService.java
+++ b/services/core/java/com/android/server/lights/LightsService.java
@@ -84,8 +84,12 @@
if (DEBUG) {
Slog.d(TAG, "Using new setBrightness path!");
}
- SurfaceControl.setDisplayBrightness(mDisplayToken,
- (float) brightness / mSurfaceControlMaximumBrightness);
+ if (brightness == 0) {
+ SurfaceControl.setDisplayBrightness(mDisplayToken, -1.0f);
+ } else {
+ SurfaceControl.setDisplayBrightness(mDisplayToken,
+ (float) (brightness - 1) / (mSurfaceControlMaximumBrightness - 1));
+ }
} else {
int color = brightness & 0x000000ff;
color = 0xff000000 | (color << 16) | (color << 8) | color;
diff --git a/services/core/java/com/android/server/location/LocationSettingsStore.java b/services/core/java/com/android/server/location/LocationSettingsStore.java
index a4b6d97..dc5628e 100644
--- a/services/core/java/com/android/server/location/LocationSettingsStore.java
+++ b/services/core/java/com/android/server/location/LocationSettingsStore.java
@@ -237,9 +237,6 @@
IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ");
int userId = ActivityManager.getCurrentUser();
- ipw.println("--Location Settings--");
- ipw.increaseIndent();
-
ipw.print("Location Enabled: ");
ipw.println(isLocationEnabled(userId));
diff --git a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
index 7820cd7..2cf920d 100644
--- a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
+++ b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
@@ -83,6 +83,24 @@
mContext = context;
}
+ @NonNull
+ public List<MediaRoute2Info> getSystemRoutes() {
+ final int uid = Binder.getCallingUid();
+ final int userId = UserHandle.getUserId(uid);
+
+ Collection<MediaRoute2Info> systemRoutes;
+ synchronized (mLock) {
+ UserRecord userRecord = mUserRecords.get(userId);
+ if (userRecord == null) {
+ userRecord = new UserRecord(userId);
+ mUserRecords.put(userId, userRecord);
+ initializeUserLocked(userRecord);
+ }
+ systemRoutes = userRecord.mHandler.mSystemProvider.getProviderInfo().getRoutes();
+ }
+ return new ArrayList<>(systemRoutes);
+ }
+
public void registerClient(@NonNull IMediaRouter2Client client,
@NonNull String packageName) {
Objects.requireNonNull(client, "client must not be null");
diff --git a/services/core/java/com/android/server/media/MediaRouterService.java b/services/core/java/com/android/server/media/MediaRouterService.java
index ecc1aba..9336af4 100644
--- a/services/core/java/com/android/server/media/MediaRouterService.java
+++ b/services/core/java/com/android/server/media/MediaRouterService.java
@@ -443,6 +443,12 @@
// Binder call
@Override
+ public List<MediaRoute2Info> getSystemRoutes() {
+ return mService2.getSystemRoutes();
+ }
+
+ // Binder call
+ @Override
public void registerClient2(IMediaRouter2Client client, String packageName) {
final int uid = Binder.getCallingUid();
if (!validatePackageName(uid, packageName)) {
diff --git a/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java b/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java
index 620775e..4f64177 100644
--- a/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java
+++ b/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java
@@ -42,8 +42,8 @@
private static final String TAG = "MR2SystemProvider";
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
- private static final String DEFAULT_ROUTE_ID = "DEFAULT_ROUTE";
- private static final String BLUETOOTH_ROUTE_ID = "BLUETOOTH_ROUTE";
+ static final String DEFAULT_ROUTE_ID = "DEFAULT_ROUTE";
+ static final String BLUETOOTH_ROUTE_ID = "BLUETOOTH_ROUTE";
// TODO: Move these to a proper place
public static final String CATEGORY_LIVE_AUDIO = "android.media.intent.category.LIVE_AUDIO";
@@ -191,12 +191,20 @@
publishRoutes();
}
+
+ /**
+ * The first route should be the currently selected system route.
+ * For example, if there are two system routes (BT and device speaker),
+ * BT will be the first route in the list.
+ *
+ * TODO: Support multiple BT devices
+ */
void publishRoutes() {
- MediaRoute2ProviderInfo.Builder builder = new MediaRoute2ProviderInfo.Builder()
- .addRoute(mDefaultRoute);
+ MediaRoute2ProviderInfo.Builder builder = new MediaRoute2ProviderInfo.Builder();
if (mBluetoothA2dpRoute != null) {
builder.addRoute(mBluetoothA2dpRoute);
}
+ builder.addRoute(mDefaultRoute);
setAndNotifyProviderInfo(builder.build());
}
}
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index b60306b..d5f2d7e 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -2083,10 +2083,10 @@
@Override
public void updateAutogroupSummary(String key, boolean needsOngoingFlag) {
- String pkg = null;
+ String pkg;
synchronized (mNotificationLock) {
NotificationRecord r = mNotificationsByKey.get(key);
- pkg = r.sbn.getPackageName();
+ pkg = r != null && r.sbn != null ? r.sbn.getPackageName() : null;
}
boolean isAppForeground = pkg != null
&& mActivityManager.getPackageImportance(pkg) == IMPORTANCE_FOREGROUND;
diff --git a/services/core/java/com/android/server/pm/BackgroundDexOptService.java b/services/core/java/com/android/server/pm/BackgroundDexOptService.java
index 08e55d3..c712431 100644
--- a/services/core/java/com/android/server/pm/BackgroundDexOptService.java
+++ b/services/core/java/com/android/server/pm/BackgroundDexOptService.java
@@ -34,8 +34,6 @@
import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.storage.StorageManager;
-import android.provider.DeviceConfig;
-import android.text.TextUtils;
import android.util.ArraySet;
import android.util.Log;
import android.util.StatsLog;
@@ -86,12 +84,6 @@
// Used for calculating space threshold for downgrading unused apps.
private static final int LOW_THRESHOLD_MULTIPLIER_FOR_DOWNGRADE = 2;
- private static final int DEFAULT_INACTIVE_APP_THRESHOLD_DAYS = 10;
-
- private static final String DOWNGRADE_UNUSED_APPS_ENABLED = "downgrade_unused_apps_enabled";
- private static final String INACTIVE_APP_THRESHOLD_DAYS = "inactive_app_threshold_days";
- private static final String LOW_STORAGE_MULTIPLIER_FOR_DOWNGRADE =
- "low_storage_threshold_multiplier_for_downgrade";
/**
* Set of failed packages remembered across job runs.
@@ -111,6 +103,8 @@
private final AtomicBoolean mExitPostBootUpdate = new AtomicBoolean(false);
private final File mDataDir = Environment.getDataDirectory();
+ private static final long mDowngradeUnusedAppsThresholdInMillis =
+ getDowngradeUnusedAppsThresholdInMillis();
public static void schedule(Context context) {
if (isBackgroundDexoptDisabled()) {
@@ -352,14 +346,14 @@
// Only downgrade apps when space is low on device.
// Threshold is selected above the lowStorageThreshold so that we can pro-actively clean
// up disk before user hits the actual lowStorageThreshold.
- final long lowStorageThresholdForDowngrade = getLowThresholdMultiplierForDowngrade()
+ final long lowStorageThresholdForDowngrade = LOW_THRESHOLD_MULTIPLIER_FOR_DOWNGRADE
* lowStorageThreshold;
boolean shouldDowngrade = shouldDowngrade(lowStorageThresholdForDowngrade);
Log.d(TAG, "Should Downgrade " + shouldDowngrade);
if (shouldDowngrade) {
Set<String> unusedPackages =
- pm.getUnusedPackages(getDowngradeUnusedAppsThresholdInMillis());
- Log.d(TAG, "Unused Packages " + String.join(",", unusedPackages));
+ pm.getUnusedPackages(mDowngradeUnusedAppsThresholdInMillis);
+ Log.d(TAG, "Unsused Packages " + String.join(",", unusedPackages));
if (!unusedPackages.isEmpty()) {
for (String pkg : unusedPackages) {
@@ -368,9 +362,12 @@
// Should be aborted by the scheduler.
return abortCode;
}
- if (downgradePackage(pm, pkg)) {
+ if (downgradePackage(pm, pkg, /*isForPrimaryDex*/ true)) {
updatedPackages.add(pkg);
}
+ if (supportSecondaryDex) {
+ downgradePackage(pm, pkg, /*isForPrimaryDex*/ false);
+ }
}
pkgs = new ArraySet<>(pkgs);
@@ -418,45 +415,39 @@
* Try to downgrade the package to a smaller compilation filter.
* eg. if the package is in speed-profile the package will be downgraded to verify.
* @param pm PackageManagerService
- * @param pkg The package to be downgraded
- * @return true if the package was downgraded
+ * @param pkg The package to be downgraded.
+ * @param isForPrimaryDex. Apps can have several dex file, primary and secondary.
+ * @return true if the package was downgraded.
*/
- private boolean downgradePackage(PackageManagerService pm, String pkg) {
+ private boolean downgradePackage(PackageManagerService pm, String pkg,
+ boolean isForPrimaryDex) {
Log.d(TAG, "Downgrading " + pkg);
- boolean downgradedPrimary = false;
+ boolean dex_opt_performed = false;
int reason = PackageManagerService.REASON_INACTIVE_PACKAGE_DOWNGRADE;
int dexoptFlags = DexoptOptions.DEXOPT_BOOT_COMPLETE
| DexoptOptions.DEXOPT_IDLE_BACKGROUND_JOB
| DexoptOptions.DEXOPT_DOWNGRADE;
-
long package_size_before = getPackageSize(pm, pkg);
- // An aggressive downgrade deletes the oat files.
- boolean aggressive = false;
- // This applies for system apps or if packages location is not a directory, i.e.
- // monolithic install.
- if (!pm.canHaveOatDir(pkg)) {
- // For apps that don't have the oat directory, instead of downgrading,
- // remove their compiler artifacts from dalvik cache.
- pm.deleteOatArtifactsOfPackage(pkg);
- aggressive = true;
- downgradedPrimary = true;
- } else {
- downgradedPrimary = performDexOptPrimary(pm, pkg, reason, dexoptFlags);
- if (supportSecondaryDex()) {
- performDexOptSecondary(pm, pkg, reason, dexoptFlags);
+ if (isForPrimaryDex) {
+ // This applies for system apps or if packages location is not a directory, i.e.
+ // monolithic install.
+ if (!pm.canHaveOatDir(pkg)) {
+ // For apps that don't have the oat directory, instead of downgrading,
+ // remove their compiler artifacts from dalvik cache.
+ pm.deleteOatArtifactsOfPackage(pkg);
+ } else {
+ dex_opt_performed = performDexOptPrimary(pm, pkg, reason, dexoptFlags);
}
+ } else {
+ dex_opt_performed = performDexOptSecondary(pm, pkg, reason, dexoptFlags);
}
- // This metric aims to log the storage savings when downgrading.
- // The way disk size is measured using getPackageSize only looks at the primary apks.
- // Any logs that are due to secondary dex files will show 0% size reduction and pollute
- // the metrics.
- if (downgradedPrimary) {
+ if (dex_opt_performed) {
StatsLog.write(StatsLog.APP_DOWNGRADED, pkg, package_size_before,
- getPackageSize(pm, pkg), aggressive);
+ getPackageSize(pm, pkg), /*aggressive=*/ false);
}
- return downgradedPrimary;
+ return dex_opt_performed;
}
private boolean supportSecondaryDex() {
@@ -480,7 +471,7 @@
* concurrent jobs because PackageDexOptimizer.performDexOpt is synchronized.
* @param pm An instance of PackageManagerService
* @param pkg The package to be downgraded.
- * @param isForPrimaryDex Apps can have several dex file, primary and secondary.
+ * @param isForPrimaryDex. Apps can have several dex file, primary and secondary.
* @return true if the package was downgraded.
*/
private boolean optimizePackage(PackageManagerService pm, String pkg,
@@ -597,6 +588,12 @@
// the checks above. This check is not "live" - the value is determined by a background
// restart with a period of ~1 minute.
PackageManagerService pm = (PackageManagerService)ServiceManager.getService("package");
+ if (pm.isStorageLow()) {
+ if (DEBUG_DEXOPT) {
+ Log.i(TAG, "Low storage, skipping this run");
+ }
+ return false;
+ }
final ArraySet<String> pkgs = pm.getOptimizablePackages();
if (pkgs.isEmpty()) {
@@ -646,77 +643,17 @@
}
private static long getDowngradeUnusedAppsThresholdInMillis() {
- long defaultValue = Long.MAX_VALUE;
- if (isDowngradeFeatureEnabled()) {
- return getInactiveAppsThresholdMillis();
- }
final String sysPropKey = "pm.dexopt.downgrade_after_inactive_days";
String sysPropValue = SystemProperties.get(sysPropKey);
if (sysPropValue == null || sysPropValue.isEmpty()) {
Log.w(TAG, "SysProp " + sysPropKey + " not set");
- return defaultValue;
+ return Long.MAX_VALUE;
}
- try {
- return TimeUnit.DAYS.toMillis(Long.parseLong(sysPropValue));
- } catch (NumberFormatException e) {
- Log.w(TAG, "Couldn't parse long for pm.dexopt.downgrade_after_inactive_days: "
- + sysPropValue + ". Returning default value instead.");
- return defaultValue;
- }
+ return TimeUnit.DAYS.toMillis(Long.parseLong(sysPropValue));
}
private static boolean isBackgroundDexoptDisabled() {
return SystemProperties.getBoolean("pm.dexopt.disable_bg_dexopt" /* key */,
false /* default */);
}
-
- private static boolean isDowngradeFeatureEnabled() {
- // DeviceConfig enables the control of on device features via remotely configurable flags,
- // compared to SystemProperties which is only a way of sharing info system-widely, but are
- // not configurable on the server-side.
- String downgradeUnusedAppsEnabledFlag =
- DeviceConfig.getProperty(
- DeviceConfig.NAMESPACE_PACKAGE_MANAGER_SERVICE,
- DOWNGRADE_UNUSED_APPS_ENABLED);
- return !TextUtils.isEmpty(downgradeUnusedAppsEnabledFlag)
- && Boolean.parseBoolean(downgradeUnusedAppsEnabledFlag);
- }
-
- private static long getInactiveAppsThresholdMillis() {
- long defaultValue = TimeUnit.DAYS.toMillis(DEFAULT_INACTIVE_APP_THRESHOLD_DAYS);
- String inactiveAppThresholdDaysFlag =
- DeviceConfig.getProperty(DeviceConfig.NAMESPACE_PACKAGE_MANAGER_SERVICE,
- INACTIVE_APP_THRESHOLD_DAYS);
- if (!TextUtils.isEmpty(inactiveAppThresholdDaysFlag)) {
- try {
- return TimeUnit.DAYS.toMillis(Long.parseLong(inactiveAppThresholdDaysFlag));
- } catch (NumberFormatException e) {
- Log.w(TAG, "Couldn't parse long for " + INACTIVE_APP_THRESHOLD_DAYS + " flag: "
- + inactiveAppThresholdDaysFlag + ". Returning default value instead.");
- return defaultValue;
- }
- }
- return defaultValue;
- }
-
- private static int getLowThresholdMultiplierForDowngrade() {
- int defaultValue = LOW_THRESHOLD_MULTIPLIER_FOR_DOWNGRADE;
- if (isDowngradeFeatureEnabled()) {
- String lowStorageThresholdMultiplierFlag =
- DeviceConfig.getProperty(DeviceConfig.NAMESPACE_PACKAGE_MANAGER_SERVICE,
- LOW_STORAGE_MULTIPLIER_FOR_DOWNGRADE);
- if (!TextUtils.isEmpty(lowStorageThresholdMultiplierFlag)) {
- try {
- return Integer.parseInt(lowStorageThresholdMultiplierFlag);
- } catch (NumberFormatException e) {
- Log.w(TAG, "Couldn't parse long for "
- + LOW_STORAGE_MULTIPLIER_FOR_DOWNGRADE + " flag: "
- + lowStorageThresholdMultiplierFlag
- + ". Returning default value instead.");
- return defaultValue;
- }
- }
- }
- return defaultValue;
- }
}
diff --git a/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java b/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java
index d6108b7c..d2a6b42 100644
--- a/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java
+++ b/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java
@@ -202,6 +202,7 @@
final List<ResolveInfo> apps =
mInjector.getPackageManagerInternal().queryIntentActivities(
launchIntent,
+ launchIntent.resolveTypeIfNeeded(mContext.getContentResolver()),
MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE,
callingUid,
userId);
diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java
index bd95667..f7fd1b2 100644
--- a/services/core/java/com/android/server/pm/LauncherAppsService.java
+++ b/services/core/java/com/android/server/pm/LauncherAppsService.java
@@ -344,6 +344,7 @@
final PackageManagerInternal pmInt =
LocalServices.getService(PackageManagerInternal.class);
List<ResolveInfo> apps = pmInt.queryIntentActivities(intent,
+ intent.resolveTypeIfNeeded(mContext.getContentResolver()),
PackageManager.MATCH_DIRECT_BOOT_AWARE
| PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
callingUid, user.getIdentifier());
@@ -468,6 +469,7 @@
matchIntent.addCategory(Intent.CATEGORY_LAUNCHER);
matchIntent.setPackage(packageName);
final List<ResolveInfo> infoList = pmInt.queryIntentActivities(matchIntent,
+ matchIntent.resolveTypeIfNeeded(mContext.getContentResolver()),
PackageManager.MATCH_DISABLED_COMPONENTS, Binder.getCallingUid(),
getCallingUserId());
final int size = infoList.size();
@@ -539,6 +541,7 @@
final PackageManagerInternal pmInt =
LocalServices.getService(PackageManagerInternal.class);
List<ResolveInfo> apps = pmInt.queryIntentActivities(intent,
+ intent.resolveTypeIfNeeded(mContext.getContentResolver()),
PackageManager.MATCH_DIRECT_BOOT_AWARE
| PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
callingUid, user.getIdentifier());
@@ -842,6 +845,7 @@
// as calling startActivityAsUser ignores the category and just
// resolves based on the component if present.
List<ResolveInfo> apps = pmInt.queryIntentActivities(launchIntent,
+ launchIntent.resolveTypeIfNeeded(mContext.getContentResolver()),
PackageManager.MATCH_DIRECT_BOOT_AWARE
| PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
callingUid, user.getIdentifier());
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index fa98c96..eebc8d7 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -13218,10 +13218,6 @@
// Check if installing from ADB
if ((installFlags & PackageManager.INSTALL_FROM_ADB) != 0) {
- // Do not run verification in a test harness environment
- if (ActivityManager.isRunningInTestHarness()) {
- return false;
- }
if (isUserRestricted(userId, UserManager.ENSURE_VERIFY_APPS)) {
return true;
}
@@ -22874,39 +22870,79 @@
return pkg == null ? null : pkg.packageName;
}
+ /**
+ * Only keep package names that refer to {@link PackageParser.Package#isSystem system}
+ * packages.
+ *
+ * @param pkgNames The packages to filter
+ *
+ * @return The filtered packages
+ */
+ private @NonNull String[] filterOnlySystemPackages(@Nullable String... pkgNames) {
+ if (pkgNames == null) {
+ return ArrayUtils.emptyArray(String.class);
+ }
+
+ ArrayList<String> systemPackageNames = new ArrayList<>(pkgNames.length);
+
+ for (String pkgName: pkgNames) {
+ synchronized (mPackages) {
+ if (pkgName == null) {
+ continue;
+ }
+
+ PackageParser.Package pkg = getPackage(pkgName);
+ if (pkg == null) {
+ Log.w(TAG, "Could not find package " + pkgName);
+ continue;
+ }
+
+ if (!pkg.isSystem()) {
+ Log.w(TAG, pkgName + " is not system");
+ continue;
+ }
+
+ systemPackageNames.add(pkgName);
+ }
+ }
+
+ return systemPackageNames.toArray(new String[]{});
+ }
+
@Override
public @NonNull String[] getKnownPackageNames(int knownPackage, int userId) {
- switch(knownPackage) {
+ switch (knownPackage) {
case PackageManagerInternal.PACKAGE_BROWSER:
return new String[]{mPermissionManager.getDefaultBrowser(userId)};
case PackageManagerInternal.PACKAGE_INSTALLER:
- return new String[]{mRequiredInstallerPackage};
+ return filterOnlySystemPackages(mRequiredInstallerPackage);
case PackageManagerInternal.PACKAGE_SETUP_WIZARD:
- return new String[]{mSetupWizardPackage};
+ return filterOnlySystemPackages(mSetupWizardPackage);
case PackageManagerInternal.PACKAGE_SYSTEM:
return new String[]{"android"};
case PackageManagerInternal.PACKAGE_VERIFIER:
- return new String[]{mRequiredVerifierPackage};
+ return filterOnlySystemPackages(mRequiredVerifierPackage);
case PackageManagerInternal.PACKAGE_SYSTEM_TEXT_CLASSIFIER:
- return new String[]{mSystemTextClassifierPackage};
+ return filterOnlySystemPackages(mSystemTextClassifierPackage);
case PackageManagerInternal.PACKAGE_PERMISSION_CONTROLLER:
- return new String[]{mRequiredPermissionControllerPackage};
+ return filterOnlySystemPackages(mRequiredPermissionControllerPackage);
case PackageManagerInternal.PACKAGE_WELLBEING:
- return new String[]{mWellbeingPackage};
+ return filterOnlySystemPackages(mWellbeingPackage);
case PackageManagerInternal.PACKAGE_DOCUMENTER:
- return new String[]{mDocumenterPackage};
+ return filterOnlySystemPackages(mDocumenterPackage);
case PackageManagerInternal.PACKAGE_CONFIGURATOR:
- return new String[]{mConfiguratorPackage};
+ return filterOnlySystemPackages(mConfiguratorPackage);
case PackageManagerInternal.PACKAGE_INCIDENT_REPORT_APPROVER:
- return new String[]{mIncidentReportApproverPackage};
+ return filterOnlySystemPackages(mIncidentReportApproverPackage);
case PackageManagerInternal.PACKAGE_APP_PREDICTOR:
- return new String[]{mAppPredictionServicePackage};
+ return filterOnlySystemPackages(mAppPredictionServicePackage);
case PackageManagerInternal.PACKAGE_TELEPHONY:
- return mTelephonyPackages;
+ return filterOnlySystemPackages(mTelephonyPackages);
case PackageManagerInternal.PACKAGE_WIFI:
- return new String[]{mWifiPackage};
+ return filterOnlySystemPackages(mWifiPackage);
+ default:
+ return ArrayUtils.emptyArray(String.class);
}
- return ArrayUtils.emptyArray(String.class);
}
@Override
@@ -23061,8 +23097,7 @@
@Override
public List<ResolveInfo> queryIntentActivities(
- Intent intent, int flags, int filterCallingUid, int userId) {
- final String resolvedType = intent.resolveTypeIfNeeded(mContext.getContentResolver());
+ Intent intent, String resolvedType, int flags, int filterCallingUid, int userId) {
return PackageManagerService.this
.queryIntentActivitiesInternal(intent, resolvedType, flags, filterCallingUid,
userId, false /*resolveForStart*/, true /*allowDynamicSplits*/);
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 5f3650c..69c7cf2 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -3348,7 +3348,8 @@
int flags, ComponentName cn, String scheme, PatternMatcher ssp,
IntentFilter.AuthorityEntry auth, PatternMatcher path, int userId) {
final List<ResolveInfo> ri =
- pmInternal.queryIntentActivities(intent, flags, Binder.getCallingUid(), 0);
+ pmInternal.queryIntentActivities(
+ intent, intent.getType(), flags, Binder.getCallingUid(), 0);
if (PackageManagerService.DEBUG_PREFERRED) {
Log.d(TAG, "Queried " + intent + " results: " + ri);
}
diff --git a/services/core/java/com/android/server/pm/StagingManager.java b/services/core/java/com/android/server/pm/StagingManager.java
index 3390ca7..5bb42d4 100644
--- a/services/core/java/com/android/server/pm/StagingManager.java
+++ b/services/core/java/com/android/server/pm/StagingManager.java
@@ -45,6 +45,7 @@
import android.os.PowerManager;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.os.storage.StorageManager;
import android.util.IntArray;
import android.util.Slog;
import android.util.SparseArray;
@@ -75,6 +76,7 @@
private final PackageInstallerService mPi;
private final ApexManager mApexManager;
private final PowerManager mPowerManager;
+ private final Context mContext;
private final PreRebootVerificationHandler mPreRebootVerificationHandler;
@GuardedBy("mStagedSessions")
@@ -83,6 +85,7 @@
StagingManager(PackageInstallerService pi, ApexManager am, Context context) {
mPi = pi;
mApexManager = am;
+ mContext = context;
mPowerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
mPreRebootVerificationHandler = new PreRebootVerificationHandler(
BackgroundThread.get().getLooper());
@@ -539,6 +542,10 @@
mPreRebootVerificationHandler.startPreRebootVerification(session.sessionId);
}
+ private int parentOrOwnSessionId(PackageInstallerSession session) {
+ return session.hasParentSessionId() ? session.getParentSessionId() : session.sessionId;
+ }
+
/**
* <p> Check if the session provided is non-overlapping with the active staged sessions.
*
@@ -561,6 +568,9 @@
"Cannot stage session " + session.sessionId + " with package name null");
}
+ boolean supportsCheckpoint = ((StorageManager) mContext.getSystemService(
+ Context.STORAGE_SERVICE)).isCheckpointSupported();
+
synchronized (mStagedSessions) {
for (int i = 0; i < mStagedSessions.size(); i++) {
final PackageInstallerSession stagedSession = mStagedSessions.valueAt(i);
@@ -601,7 +611,17 @@
+ stagedSession.sessionId, null);
}
- // TODO(b/141843321): Add support for staging multiple sessions in apexd
+ // Staging multiple root sessions is not allowed if device doesn't support
+ // checkpoint. If session and stagedSession do not have common ancestor, they are
+ // from two different root sessions.
+ if (!supportsCheckpoint
+ && parentOrOwnSessionId(session) != parentOrOwnSessionId(stagedSession)) {
+ throw new PackageManagerException(
+ PackageManager.INSTALL_FAILED_OTHER_STAGED_SESSION_IN_PROGRESS,
+ "Cannot stage multiple sessions without checkpoint support", null);
+ }
+
+ // TODO:b/141843321 Add support for staging multiple sessions in apexd
// Since apexd doesn't support multiple staged sessions yet, we have to careful how
// we handle apex sessions. We want to allow a set of apex sessions under the same
// parent to be staged when there is no previously staged apex sessions.
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 5e1d93f..3e528f4 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -3334,27 +3334,17 @@
return;
}
Bundle args = null;
- if (deviceId > Integer.MIN_VALUE) {
+ if (deviceId > Integer.MIN_VALUE || hint != null) {
args = new Bundle();
- args.putInt(Intent.EXTRA_ASSIST_INPUT_DEVICE_ID, deviceId);
- }
- if ((mContext.getResources().getConfiguration().uiMode
- & Configuration.UI_MODE_TYPE_MASK) == Configuration.UI_MODE_TYPE_TELEVISION) {
- // On TV, use legacy handling until assistants are implemented in the proper way.
- ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
- .launchLegacyAssist(hint, mCurrentUserId, args);
- } else {
+ if (deviceId > Integer.MIN_VALUE) {
+ args.putInt(Intent.EXTRA_ASSIST_INPUT_DEVICE_ID, deviceId);
+ }
if (hint != null) {
- if (args == null) {
- args = new Bundle();
- }
args.putBoolean(hint, true);
}
- StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
- if (statusbar != null) {
- statusbar.startAssist(args);
- }
}
+ ((SearchManager) mContext.createContextAsUser(UserHandle.of(mCurrentUserId), 0)
+ .getSystemService(Context.SEARCH_SERVICE)).launchAssist(args);
}
/** Launches ACTION_VOICE_ASSIST. Does nothing on keyguard. */
diff --git a/services/core/java/com/android/server/recoverysystem/RecoverySystemService.java b/services/core/java/com/android/server/recoverysystem/RecoverySystemService.java
index d78aaa5..fe18fbf 100644
--- a/services/core/java/com/android/server/recoverysystem/RecoverySystemService.java
+++ b/services/core/java/com/android/server/recoverysystem/RecoverySystemService.java
@@ -27,6 +27,7 @@
import android.os.SystemProperties;
import android.util.Slog;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.server.SystemService;
import libcore.io.IoUtils;
@@ -35,6 +36,7 @@
import java.io.DataOutputStream;
import java.io.FileWriter;
import java.io.IOException;
+import java.nio.charset.StandardCharsets;
/**
* The recovery system service is responsible for coordinating recovery related
@@ -43,7 +45,7 @@
* triggers /system/bin/uncrypt via init to de-encrypt an OTA package on the
* /data partition so that it can be accessed under the recovery image.
*/
-public final class RecoverySystemService extends SystemService {
+public class RecoverySystemService extends IRecoverySystem.Stub {
private static final String TAG = "RecoverySystemService";
private static final boolean DEBUG = false;
@@ -51,191 +53,321 @@
private static final String UNCRYPT_SOCKET = "uncrypt";
// The init services that communicate with /system/bin/uncrypt.
- private static final String INIT_SERVICE_UNCRYPT = "init.svc.uncrypt";
- private static final String INIT_SERVICE_SETUP_BCB = "init.svc.setup-bcb";
- private static final String INIT_SERVICE_CLEAR_BCB = "init.svc.clear-bcb";
-
- private static final int SOCKET_CONNECTION_MAX_RETRY = 30;
+ @VisibleForTesting
+ static final String INIT_SERVICE_UNCRYPT = "init.svc.uncrypt";
+ @VisibleForTesting
+ static final String INIT_SERVICE_SETUP_BCB = "init.svc.setup-bcb";
+ @VisibleForTesting
+ static final String INIT_SERVICE_CLEAR_BCB = "init.svc.clear-bcb";
private static final Object sRequestLock = new Object();
- private Context mContext;
+ private static final int SOCKET_CONNECTION_MAX_RETRY = 30;
- public RecoverySystemService(Context context) {
- super(context);
- mContext = context;
+ private final Injector mInjector;
+ private final Context mContext;
+
+ static class Injector {
+ protected final Context mContext;
+
+ Injector(Context context) {
+ mContext = context;
+ }
+
+ public Context getContext() {
+ return mContext;
+ }
+
+ public PowerManager getPowerManager() {
+ return (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
+ }
+
+ public String systemPropertiesGet(String key) {
+ return SystemProperties.get(key);
+ }
+
+ public void systemPropertiesSet(String key, String value) {
+ SystemProperties.set(key, value);
+ }
+
+ public boolean uncryptPackageFileDelete() {
+ return RecoverySystem.UNCRYPT_PACKAGE_FILE.delete();
+ }
+
+ public String getUncryptPackageFileName() {
+ return RecoverySystem.UNCRYPT_PACKAGE_FILE.getName();
+ }
+
+ public FileWriter getUncryptPackageFileWriter() throws IOException {
+ return new FileWriter(RecoverySystem.UNCRYPT_PACKAGE_FILE);
+ }
+
+ public UncryptSocket connectService() {
+ UncryptSocket socket = new UncryptSocket();
+ if (!socket.connectService()) {
+ socket.close();
+ return null;
+ }
+ return socket;
+ }
+
+ public void threadSleep(long millis) throws InterruptedException {
+ Thread.sleep(millis);
+ }
}
- @Override
- public void onStart() {
- publishBinderService(Context.RECOVERY_SERVICE, new BinderService());
+ /**
+ * Handles the lifecycle events for the RecoverySystemService.
+ */
+ public static final class Lifecycle extends SystemService {
+ public Lifecycle(Context context) {
+ super(context);
+ }
+
+ @Override
+ public void onStart() {
+ RecoverySystemService recoverySystemService = new RecoverySystemService(getContext());
+ publishBinderService(Context.RECOVERY_SERVICE, recoverySystemService);
+ }
}
- private final class BinderService extends IRecoverySystem.Stub {
- @Override // Binder call
- public boolean uncrypt(String filename, IRecoverySystemProgressListener listener) {
- if (DEBUG) Slog.d(TAG, "uncrypt: " + filename);
+ private RecoverySystemService(Context context) {
+ this(new Injector(context));
+ }
- synchronized (sRequestLock) {
- mContext.enforceCallingOrSelfPermission(android.Manifest.permission.RECOVERY, null);
+ @VisibleForTesting
+ RecoverySystemService(Injector injector) {
+ mInjector = injector;
+ mContext = injector.getContext();
+ }
- final boolean available = checkAndWaitForUncryptService();
- if (!available) {
- Slog.e(TAG, "uncrypt service is unavailable.");
- return false;
- }
+ @Override // Binder call
+ public boolean uncrypt(String filename, IRecoverySystemProgressListener listener) {
+ if (DEBUG) Slog.d(TAG, "uncrypt: " + filename);
- // Write the filename into UNCRYPT_PACKAGE_FILE to be read by
- // uncrypt.
- RecoverySystem.UNCRYPT_PACKAGE_FILE.delete();
+ synchronized (sRequestLock) {
+ mContext.enforceCallingOrSelfPermission(android.Manifest.permission.RECOVERY, null);
- try (FileWriter uncryptFile = new FileWriter(RecoverySystem.UNCRYPT_PACKAGE_FILE)) {
- uncryptFile.write(filename + "\n");
- } catch (IOException e) {
- Slog.e(TAG, "IOException when writing \"" +
- RecoverySystem.UNCRYPT_PACKAGE_FILE + "\":", e);
- return false;
- }
+ if (!checkAndWaitForUncryptService()) {
+ Slog.e(TAG, "uncrypt service is unavailable.");
+ return false;
+ }
- // Trigger uncrypt via init.
- SystemProperties.set("ctl.start", "uncrypt");
+ // Write the filename into uncrypt package file to be read by
+ // uncrypt.
+ mInjector.uncryptPackageFileDelete();
- // Connect to the uncrypt service socket.
- LocalSocket socket = connectService();
- if (socket == null) {
- Slog.e(TAG, "Failed to connect to uncrypt socket");
- return false;
- }
+ try (FileWriter uncryptFile = mInjector.getUncryptPackageFileWriter()) {
+ uncryptFile.write(filename + "\n");
+ } catch (IOException e) {
+ Slog.e(TAG, "IOException when writing \""
+ + mInjector.getUncryptPackageFileName() + "\":", e);
+ return false;
+ }
- // Read the status from the socket.
- DataInputStream dis = null;
- DataOutputStream dos = null;
- try {
- dis = new DataInputStream(socket.getInputStream());
- dos = new DataOutputStream(socket.getOutputStream());
- int lastStatus = Integer.MIN_VALUE;
- while (true) {
- int status = dis.readInt();
- // Avoid flooding the log with the same message.
- if (status == lastStatus && lastStatus != Integer.MIN_VALUE) {
- continue;
- }
- lastStatus = status;
+ // Trigger uncrypt via init.
+ mInjector.systemPropertiesSet("ctl.start", "uncrypt");
- if (status >= 0 && status <= 100) {
- // Update status
- Slog.i(TAG, "uncrypt read status: " + status);
- if (listener != null) {
- try {
- listener.onProgress(status);
- } catch (RemoteException ignored) {
- Slog.w(TAG, "RemoteException when posting progress");
- }
- }
- if (status == 100) {
- Slog.i(TAG, "uncrypt successfully finished.");
- // Ack receipt of the final status code. uncrypt
- // waits for the ack so the socket won't be
- // destroyed before we receive the code.
- dos.writeInt(0);
- break;
- }
- } else {
- // Error in /system/bin/uncrypt.
- Slog.e(TAG, "uncrypt failed with status: " + status);
- // Ack receipt of the final status code. uncrypt waits
- // for the ack so the socket won't be destroyed before
- // we receive the code.
- dos.writeInt(0);
- return false;
- }
+ // Connect to the uncrypt service socket.
+ UncryptSocket socket = mInjector.connectService();
+ if (socket == null) {
+ Slog.e(TAG, "Failed to connect to uncrypt socket");
+ return false;
+ }
+
+ // Read the status from the socket.
+ try {
+ int lastStatus = Integer.MIN_VALUE;
+ while (true) {
+ int status = socket.getPercentageUncrypted();
+ // Avoid flooding the log with the same message.
+ if (status == lastStatus && lastStatus != Integer.MIN_VALUE) {
+ continue;
}
- } catch (IOException e) {
- Slog.e(TAG, "IOException when reading status: ", e);
- return false;
- } finally {
- IoUtils.closeQuietly(dis);
- IoUtils.closeQuietly(dos);
- IoUtils.closeQuietly(socket);
- }
+ lastStatus = status;
+ if (status >= 0 && status <= 100) {
+ // Update status
+ Slog.i(TAG, "uncrypt read status: " + status);
+ if (listener != null) {
+ try {
+ listener.onProgress(status);
+ } catch (RemoteException ignored) {
+ Slog.w(TAG, "RemoteException when posting progress");
+ }
+ }
+ if (status == 100) {
+ Slog.i(TAG, "uncrypt successfully finished.");
+ // Ack receipt of the final status code. uncrypt
+ // waits for the ack so the socket won't be
+ // destroyed before we receive the code.
+ socket.sendAck();
+ break;
+ }
+ } else {
+ // Error in /system/bin/uncrypt.
+ Slog.e(TAG, "uncrypt failed with status: " + status);
+ // Ack receipt of the final status code. uncrypt waits
+ // for the ack so the socket won't be destroyed before
+ // we receive the code.
+ socket.sendAck();
+ return false;
+ }
+ }
+ } catch (IOException e) {
+ Slog.e(TAG, "IOException when reading status: ", e);
+ return false;
+ } finally {
+ socket.close();
+ }
+
+ return true;
+ }
+ }
+
+ @Override // Binder call
+ public boolean clearBcb() {
+ if (DEBUG) Slog.d(TAG, "clearBcb");
+ synchronized (sRequestLock) {
+ return setupOrClearBcb(false, null);
+ }
+ }
+
+ @Override // Binder call
+ public boolean setupBcb(String command) {
+ if (DEBUG) Slog.d(TAG, "setupBcb: [" + command + "]");
+ synchronized (sRequestLock) {
+ return setupOrClearBcb(true, command);
+ }
+ }
+
+ @Override // Binder call
+ public void rebootRecoveryWithCommand(String command) {
+ if (DEBUG) Slog.d(TAG, "rebootRecoveryWithCommand: [" + command + "]");
+ synchronized (sRequestLock) {
+ if (!setupOrClearBcb(true, command)) {
+ return;
+ }
+
+ // Having set up the BCB, go ahead and reboot.
+ PowerManager pm = mInjector.getPowerManager();
+ pm.reboot(PowerManager.REBOOT_RECOVERY);
+ }
+ }
+
+ /**
+ * Check if any of the init services is still running. If so, we cannot
+ * start a new uncrypt/setup-bcb/clear-bcb service right away; otherwise
+ * it may break the socket communication since init creates / deletes
+ * the socket (/dev/socket/uncrypt) on service start / exit.
+ */
+ private boolean checkAndWaitForUncryptService() {
+ for (int retry = 0; retry < SOCKET_CONNECTION_MAX_RETRY; retry++) {
+ final String uncryptService = mInjector.systemPropertiesGet(INIT_SERVICE_UNCRYPT);
+ final String setupBcbService = mInjector.systemPropertiesGet(INIT_SERVICE_SETUP_BCB);
+ final String clearBcbService = mInjector.systemPropertiesGet(INIT_SERVICE_CLEAR_BCB);
+ final boolean busy = "running".equals(uncryptService)
+ || "running".equals(setupBcbService) || "running".equals(clearBcbService);
+ if (DEBUG) {
+ Slog.i(TAG, "retry: " + retry + " busy: " + busy
+ + " uncrypt: [" + uncryptService + "]"
+ + " setupBcb: [" + setupBcbService + "]"
+ + " clearBcb: [" + clearBcbService + "]");
+ }
+
+ if (!busy) {
return true;
}
- }
- @Override // Binder call
- public boolean clearBcb() {
- if (DEBUG) Slog.d(TAG, "clearBcb");
- synchronized (sRequestLock) {
- return setupOrClearBcb(false, null);
+ try {
+ mInjector.threadSleep(1000);
+ } catch (InterruptedException e) {
+ Slog.w(TAG, "Interrupted:", e);
}
}
- @Override // Binder call
- public boolean setupBcb(String command) {
- if (DEBUG) Slog.d(TAG, "setupBcb: [" + command + "]");
- synchronized (sRequestLock) {
- return setupOrClearBcb(true, command);
- }
- }
+ return false;
+ }
- @Override // Binder call
- public void rebootRecoveryWithCommand(String command) {
- if (DEBUG) Slog.d(TAG, "rebootRecoveryWithCommand: [" + command + "]");
- synchronized (sRequestLock) {
- if (!setupOrClearBcb(true, command)) {
- return;
- }
+ private boolean setupOrClearBcb(boolean isSetup, String command) {
+ mContext.enforceCallingOrSelfPermission(android.Manifest.permission.RECOVERY, null);
- // Having set up the BCB, go ahead and reboot.
- PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
- pm.reboot(PowerManager.REBOOT_RECOVERY);
- }
- }
-
- /**
- * Check if any of the init services is still running. If so, we cannot
- * start a new uncrypt/setup-bcb/clear-bcb service right away; otherwise
- * it may break the socket communication since init creates / deletes
- * the socket (/dev/socket/uncrypt) on service start / exit.
- */
- private boolean checkAndWaitForUncryptService() {
- for (int retry = 0; retry < SOCKET_CONNECTION_MAX_RETRY; retry++) {
- final String uncryptService = SystemProperties.get(INIT_SERVICE_UNCRYPT);
- final String setupBcbService = SystemProperties.get(INIT_SERVICE_SETUP_BCB);
- final String clearBcbService = SystemProperties.get(INIT_SERVICE_CLEAR_BCB);
- final boolean busy = "running".equals(uncryptService) ||
- "running".equals(setupBcbService) || "running".equals(clearBcbService);
- if (DEBUG) {
- Slog.i(TAG, "retry: " + retry + " busy: " + busy +
- " uncrypt: [" + uncryptService + "]" +
- " setupBcb: [" + setupBcbService + "]" +
- " clearBcb: [" + clearBcbService + "]");
- }
-
- if (!busy) {
- return true;
- }
-
- try {
- Thread.sleep(1000);
- } catch (InterruptedException e) {
- Slog.w(TAG, "Interrupted:", e);
- }
- }
-
+ final boolean available = checkAndWaitForUncryptService();
+ if (!available) {
+ Slog.e(TAG, "uncrypt service is unavailable.");
return false;
}
- private LocalSocket connectService() {
- LocalSocket socket = new LocalSocket();
+ if (isSetup) {
+ mInjector.systemPropertiesSet("ctl.start", "setup-bcb");
+ } else {
+ mInjector.systemPropertiesSet("ctl.start", "clear-bcb");
+ }
+
+ // Connect to the uncrypt service socket.
+ UncryptSocket socket = mInjector.connectService();
+ if (socket == null) {
+ Slog.e(TAG, "Failed to connect to uncrypt socket");
+ return false;
+ }
+
+ try {
+ // Send the BCB commands if it's to setup BCB.
+ if (isSetup) {
+ socket.sendCommand(command);
+ }
+
+ // Read the status from the socket.
+ int status = socket.getPercentageUncrypted();
+
+ // Ack receipt of the status code. uncrypt waits for the ack so
+ // the socket won't be destroyed before we receive the code.
+ socket.sendAck();
+
+ if (status == 100) {
+ Slog.i(TAG, "uncrypt " + (isSetup ? "setup" : "clear")
+ + " bcb successfully finished.");
+ } else {
+ // Error in /system/bin/uncrypt.
+ Slog.e(TAG, "uncrypt failed with status: " + status);
+ return false;
+ }
+ } catch (IOException e) {
+ Slog.e(TAG, "IOException when communicating with uncrypt:", e);
+ return false;
+ } finally {
+ socket.close();
+ }
+
+ return true;
+ }
+
+ /**
+ * Provides a wrapper for the low-level details of framing packets sent to the uncrypt
+ * socket.
+ */
+ public static class UncryptSocket {
+ private LocalSocket mLocalSocket;
+ private DataInputStream mInputStream;
+ private DataOutputStream mOutputStream;
+
+ /**
+ * Attempt to connect to the uncrypt service. Connection will be retried for up to
+ * {@link #SOCKET_CONNECTION_MAX_RETRY} times. If the connection is unsuccessful, the
+ * socket will be closed. If the connection is successful, the connection must be closed
+ * by the caller.
+ *
+ * @return true if connection was successful, false if unsuccessful
+ */
+ public boolean connectService() {
+ mLocalSocket = new LocalSocket();
boolean done = false;
// The uncrypt socket will be created by init upon receiving the
// service request. It may not be ready by this point. So we will
// keep retrying until success or reaching timeout.
for (int retry = 0; retry < SOCKET_CONNECTION_MAX_RETRY; retry++) {
try {
- socket.connect(new LocalSocketAddress(UNCRYPT_SOCKET,
+ mLocalSocket.connect(new LocalSocketAddress(UNCRYPT_SOCKET,
LocalSocketAddress.Namespace.RESERVED));
done = true;
break;
@@ -249,71 +381,69 @@
}
if (!done) {
Slog.e(TAG, "Timed out connecting to uncrypt socket");
- return null;
- }
- return socket;
- }
-
- private boolean setupOrClearBcb(boolean isSetup, String command) {
- mContext.enforceCallingOrSelfPermission(android.Manifest.permission.RECOVERY, null);
-
- final boolean available = checkAndWaitForUncryptService();
- if (!available) {
- Slog.e(TAG, "uncrypt service is unavailable.");
+ close();
return false;
}
- if (isSetup) {
- SystemProperties.set("ctl.start", "setup-bcb");
- } else {
- SystemProperties.set("ctl.start", "clear-bcb");
- }
-
- // Connect to the uncrypt service socket.
- LocalSocket socket = connectService();
- if (socket == null) {
- Slog.e(TAG, "Failed to connect to uncrypt socket");
- return false;
- }
-
- DataInputStream dis = null;
- DataOutputStream dos = null;
try {
- dis = new DataInputStream(socket.getInputStream());
- dos = new DataOutputStream(socket.getOutputStream());
-
- // Send the BCB commands if it's to setup BCB.
- if (isSetup) {
- byte[] cmdUtf8 = command.getBytes("UTF-8");
- dos.writeInt(cmdUtf8.length);
- dos.write(cmdUtf8, 0, cmdUtf8.length);
- }
-
- // Read the status from the socket.
- int status = dis.readInt();
-
- // Ack receipt of the status code. uncrypt waits for the ack so
- // the socket won't be destroyed before we receive the code.
- dos.writeInt(0);
-
- if (status == 100) {
- Slog.i(TAG, "uncrypt " + (isSetup ? "setup" : "clear") +
- " bcb successfully finished.");
- } else {
- // Error in /system/bin/uncrypt.
- Slog.e(TAG, "uncrypt failed with status: " + status);
- return false;
- }
+ mInputStream = new DataInputStream(mLocalSocket.getInputStream());
+ mOutputStream = new DataOutputStream(mLocalSocket.getOutputStream());
} catch (IOException e) {
- Slog.e(TAG, "IOException when communicating with uncrypt:", e);
+ close();
return false;
- } finally {
- IoUtils.closeQuietly(dis);
- IoUtils.closeQuietly(dos);
- IoUtils.closeQuietly(socket);
}
return true;
}
+
+ /**
+ * Sends a command to the uncrypt service.
+ *
+ * @param command command to send to the uncrypt service
+ * @throws IOException if the socket is closed or there was an error writing to the socket
+ */
+ public void sendCommand(String command) throws IOException {
+ if (mLocalSocket.isClosed()) {
+ throw new IOException("socket is closed");
+ }
+
+ byte[] cmdUtf8 = command.getBytes(StandardCharsets.UTF_8);
+ mOutputStream.writeInt(cmdUtf8.length);
+ mOutputStream.write(cmdUtf8, 0, cmdUtf8.length);
+ }
+
+ /**
+ * Reads the status from the uncrypt service which is usually represented as a percentage.
+ * @return an integer representing the percentage completed
+ * @throws IOException if the socket was closed or there was an error reading the socket
+ */
+ public int getPercentageUncrypted() throws IOException {
+ if (mLocalSocket.isClosed()) {
+ throw new IOException("socket is closed");
+ }
+
+ return mInputStream.readInt();
+ }
+
+ /**
+ * Sends a confirmation to the uncrypt service.
+ * @throws IOException if the socket was closed or there was an error writing to the socket
+ */
+ public void sendAck() throws IOException {
+ if (mLocalSocket.isClosed()) {
+ throw new IOException("socket is closed");
+ }
+
+ mOutputStream.writeInt(0);
+ }
+
+ /**
+ * Closes the socket and all underlying data streams.
+ */
+ public void close() {
+ IoUtils.closeQuietly(mInputStream);
+ IoUtils.closeQuietly(mOutputStream);
+ IoUtils.closeQuietly(mLocalSocket);
+ }
}
}
diff --git a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
index 198bb14..01f29dc 100644
--- a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
+++ b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
@@ -49,6 +49,7 @@
import android.provider.DeviceConfig;
import android.util.ArraySet;
import android.util.IntArray;
+import android.util.LongArrayQueue;
import android.util.Slog;
import android.util.SparseBooleanArray;
@@ -126,6 +127,11 @@
private final RollbackPackageHealthObserver mPackageHealthObserver;
private final AppDataRollbackHelper mAppDataRollbackHelper;
+ // The # of milli-seconds to sleep for each received ACTION_PACKAGE_ENABLE_ROLLBACK.
+ // Used by #blockRollbackManager to test timeout in enabling rollbacks.
+ // Accessed on the handler thread only.
+ private final LongArrayQueue mSleepDuration = new LongArrayQueue();
+
// This field stores the difference in Millis between the uptime (millis since device
// has booted) and current time (device wall clock) - it's used to update rollback
// timestamps when the time is changed, by the user or by change of timezone.
@@ -182,6 +188,8 @@
File newPackageCodePath = new File(intent.getData().getPath());
+ queueSleepIfNeeded();
+
getHandler().post(() -> {
boolean success =
enableRollback(installFlags, newPackageCodePath, user, token);
@@ -414,6 +422,19 @@
Manifest.permission.TEST_MANAGE_ROLLBACKS,
"blockRollbackManager");
getHandler().post(() -> {
+ mSleepDuration.addLast(millis);
+ });
+ }
+
+ private void queueSleepIfNeeded() {
+ if (mSleepDuration.size() == 0) {
+ return;
+ }
+ long millis = mSleepDuration.removeFirst();
+ if (millis <= 0) {
+ return;
+ }
+ getHandler().post(() -> {
try {
Thread.sleep(millis);
} catch (InterruptedException e) {
@@ -1034,6 +1055,9 @@
makeRollbackAvailable(rollback);
}
}
+
+ // Clear the queue so it will never be leaked to next tests.
+ mSleepDuration.clear();
}
}
diff --git a/services/core/java/com/android/server/search/SearchManagerService.java b/services/core/java/com/android/server/search/SearchManagerService.java
index bc1a12f..1494edf 100644
--- a/services/core/java/com/android/server/search/SearchManagerService.java
+++ b/services/core/java/com/android/server/search/SearchManagerService.java
@@ -18,7 +18,6 @@
import android.app.ActivityManager;
import android.app.ActivityTaskManager;
-import android.app.IActivityManager;
import android.app.IActivityTaskManager;
import android.app.ISearchManager;
import android.app.SearchManager;
@@ -29,6 +28,7 @@
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
+import android.content.res.Configuration;
import android.database.ContentObserver;
import android.os.Binder;
import android.os.Bundle;
@@ -265,11 +265,17 @@
}
@Override
- public void launchAssist(Bundle args) {
- StatusBarManagerInternal statusBarManager =
- LocalServices.getService(StatusBarManagerInternal.class);
- if (statusBarManager != null) {
- statusBarManager.startAssist(args);
+ public void launchAssist(int userHandle, Bundle args) {
+ if ((mContext.getResources().getConfiguration().uiMode
+ & Configuration.UI_MODE_TYPE_MASK) == Configuration.UI_MODE_TYPE_TELEVISION) {
+ // On TV, use legacy handling until assistants are implemented in the proper way.
+ launchLegacyAssist(null, userHandle, args);
+ } else {
+ StatusBarManagerInternal statusBarManager =
+ LocalServices.getService(StatusBarManagerInternal.class);
+ if (statusBarManager != null) {
+ statusBarManager.startAssist(args);
+ }
}
}
@@ -298,8 +304,7 @@
return null;
}
- @Override
- public boolean launchLegacyAssist(String hint, int userHandle, Bundle args) {
+ private boolean launchLegacyAssist(String hint, int userHandle, Bundle args) {
ComponentName comp = getLegacyAssistComponent(userHandle);
if (comp == null) {
return false;
diff --git a/services/core/java/com/android/server/storage/StorageSessionController.java b/services/core/java/com/android/server/storage/StorageSessionController.java
index 72a1b9d..d76836f 100644
--- a/services/core/java/com/android/server/storage/StorageSessionController.java
+++ b/services/core/java/com/android/server/storage/StorageSessionController.java
@@ -69,15 +69,21 @@
}
/**
- * Creates a storage session associated with {@code deviceFd} for {@code vol}. Sessions can be
- * started with {@link #onVolumeReady} and removed with {@link #onVolumeUnmount} or
- * {@link #onVolumeRemove}.
+ * Creates and starts a storage session associated with {@code deviceFd} for {@code vol}.
+ * Sessions can be started with {@link #onVolumeReady} and removed with {@link #onVolumeUnmount}
+ * or {@link #onVolumeRemove}.
+ *
+ * Throws an {@link IllegalStateException} if a session for {@code vol} has already been created
*
* Does nothing if {@link #shouldHandle} is {@code false}
*
+ * Blocks until the session is started or fails
+ *
+ * @throws ExternalStorageServiceException if the session fails to start
* @throws IllegalStateException if a session has already been created for {@code vol}
*/
- public void onVolumeMount(FileDescriptor deviceFd, VolumeInfo vol) {
+ public void onVolumeMount(FileDescriptor deviceFd, VolumeInfo vol)
+ throws ExternalStorageServiceException {
if (!shouldHandle(vol)) {
return;
}
@@ -87,71 +93,22 @@
String sessionId = vol.getId();
int userId = vol.getMountUserId();
- if (deviceFd == null) {
- Slog.w(TAG, "Null fd. Session not started for vol: " + vol);
- return;
- }
-
- // Get realpath for the fd, paths that are not /dev/null need additional
- // setup by the ExternalStorageService before they can be ready
- String realPath;
- try {
- realPath = ParcelFileDescriptor.getFile(deviceFd).getPath();
- } catch (IOException e) {
- Slog.wtf(TAG, "Could not get real path from fd: " + deviceFd, e);
- return;
- }
-
- if ("/dev/null".equals(realPath)) {
- Slog.i(TAG, "Volume ready for use with id: " + sessionId);
- return;
- }
-
+ StorageUserConnection connection = null;
synchronized (mLock) {
- StorageUserConnection connection = mConnections.get(userId);
+ connection = mConnections.get(userId);
if (connection == null) {
+ Slog.i(TAG, "Creating connection for user: " + userId);
connection = new StorageUserConnection(mContext, userId, this);
mConnections.put(userId, connection);
}
Slog.i(TAG, "Creating session with id: " + sessionId);
- connection.createSession(sessionId, new ParcelFileDescriptor(deviceFd));
- }
- }
-
- /**
- * Starts a storage session associated with {@code vol} after {@link #onVolumeMount}.
- *
- * Subsequent calls will attempt to start the storage session, but does nothing if already
- * started. If the user associated with {@code vol} is not yet ready, all pending sesssions
- * can be restarted with {@link onUnlockUser}.
- *
- * Does nothing if {@link #shouldHandle} is {@code false}
- *
- * Blocks until the session is started or fails
- *
- * @throws ExternalStorageServiceException if the session fails to start
- */
- public void onVolumeReady(VolumeInfo vol) throws ExternalStorageServiceException {
- if (!shouldHandle(vol)) {
- return;
+ connection.createSession(sessionId, new ParcelFileDescriptor(deviceFd),
+ vol.getPath().getPath(), vol.getInternalPath().getPath());
}
- Slog.i(TAG, "On volume ready " + vol);
- String sessionId = vol.getId();
-
- StorageUserConnection connection = null;
- synchronized (mLock) {
- connection = mConnections.get(vol.getMountUserId());
- if (connection == null) {
- Slog.i(TAG, "Volume ready but no associated connection");
- return;
- }
- }
-
- connection.initSession(sessionId, vol.getPath().getPath(),
- vol.getInternalPath().getPath());
-
- if (isReady()) {
+ // At boot, a volume can be mounted before user is unlocked, in that case, we create it
+ // above and save it so that we can restart all sessions when the user is unlocked
+ if (mExternalStorageServiceComponent != null) {
connection.startSession(sessionId);
} else {
Slog.i(TAG, "Controller not initialised, session not started " + sessionId);
@@ -205,14 +162,10 @@
if (connection != null) {
String sessionId = vol.getId();
- if (isReady()) {
- try {
- connection.removeSessionAndWait(sessionId);
- } catch (ExternalStorageServiceException e) {
- Slog.e(TAG, "Failed to end session for vol with id: " + sessionId, e);
- }
- } else {
- Slog.i(TAG, "Controller not initialised, session not ended " + sessionId);
+ try {
+ connection.removeSessionAndWait(sessionId);
+ } catch (ExternalStorageServiceException e) {
+ Slog.e(TAG, "Failed to end session for vol with id: " + sessionId, e);
}
}
}
@@ -232,7 +185,7 @@
Slog.i(TAG, "On user unlock " + userId);
if (userId == 0) {
- init();
+ initExternalStorageServiceComponent();
}
StorageUserConnection connection = null;
@@ -259,13 +212,6 @@
return;
}
- if (!isReady()) {
- synchronized (mLock) {
- mConnections.clear();
- }
- return;
- }
-
SparseArray<StorageUserConnection> connections = new SparseArray();
synchronized (mLock) {
mIsResetting = true;
@@ -311,7 +257,7 @@
}
}
- private void init() throws ExternalStorageServiceException {
+ private void initExternalStorageServiceComponent() throws ExternalStorageServiceException {
Slog.i(TAG, "Initialialising...");
ProviderInfo provider = mContext.getPackageManager().resolveContentProvider(
MediaStore.AUTHORITY, PackageManager.MATCH_DIRECT_BOOT_AWARE
@@ -415,8 +361,4 @@
private boolean shouldHandle(@Nullable VolumeInfo vol) {
return mIsFuseEnabled && !mIsResetting && (vol == null || isEmulatedOrPublic(vol));
}
-
- private boolean isReady() {
- return mExternalStorageServiceComponent != null;
- }
}
diff --git a/services/core/java/com/android/server/storage/StorageUserConnection.java b/services/core/java/com/android/server/storage/StorageUserConnection.java
index 24b56a4..7c47730 100644
--- a/services/core/java/com/android/server/storage/StorageUserConnection.java
+++ b/services/core/java/com/android/server/storage/StorageUserConnection.java
@@ -75,46 +75,20 @@
/**
* Creates and stores a storage {@link Session}.
*
- * Created sessions must be initialised with {@link #initSession} before starting with
- * {@link #startSession}.
- *
* They must also be cleaned up with {@link #removeSession}.
*
* @throws IllegalArgumentException if a {@code Session} with {@code sessionId} already exists
*/
- public void createSession(String sessionId, ParcelFileDescriptor pfd) {
+ public void createSession(String sessionId, ParcelFileDescriptor pfd, String upperPath,
+ String lowerPath) {
Preconditions.checkNotNull(sessionId);
Preconditions.checkNotNull(pfd);
+ Preconditions.checkNotNull(upperPath);
+ Preconditions.checkNotNull(lowerPath);
synchronized (mLock) {
Preconditions.checkArgument(!mSessions.containsKey(sessionId));
- mSessions.put(sessionId, new Session(sessionId, pfd));
- }
- }
-
- /**
- * Initialise a storage {@link Session}.
- *
- * Initialised sessions can be started with {@link #startSession}.
- *
- * They must also be cleaned up with {@link #removeSession}.
- *
- * @throws IllegalArgumentException if {@code sessionId} does not exist or is initialised
- */
- public void initSession(String sessionId, String upperPath, String lowerPath) {
- synchronized (mLock) {
- Session session = mSessions.get(sessionId);
- if (session == null) {
- throw new IllegalStateException("Failed to initialise non existent session. Id: "
- + sessionId + ". Upper path: " + upperPath + ". Lower path: " + lowerPath);
- } else if (session.isInitialisedLocked()) {
- throw new IllegalStateException("Already initialised session. Id: "
- + sessionId + ". Upper path: " + upperPath + ". Lower path: " + lowerPath);
- } else {
- session.upperPath = upperPath;
- session.lowerPath = lowerPath;
- Slog.i(TAG, "Initialised session: " + session);
- }
+ mSessions.put(sessionId, new Session(sessionId, pfd, upperPath, lowerPath));
}
}
@@ -440,14 +414,14 @@
private static final class Session implements AutoCloseable {
public final String sessionId;
public final ParcelFileDescriptor pfd;
- @GuardedBy("mLock")
- public String lowerPath;
- @GuardedBy("mLock")
- public String upperPath;
+ public final String lowerPath;
+ public final String upperPath;
- Session(String sessionId, ParcelFileDescriptor pfd) {
+ Session(String sessionId, ParcelFileDescriptor pfd, String upperPath, String lowerPath) {
this.sessionId = sessionId;
this.pfd = pfd;
+ this.upperPath = upperPath;
+ this.lowerPath = lowerPath;
}
@Override
diff --git a/services/core/java/com/android/server/updates/EmergencyNumberDbInstallReceiver.java b/services/core/java/com/android/server/updates/EmergencyNumberDbInstallReceiver.java
index cb0b45c..c78a8e6 100644
--- a/services/core/java/com/android/server/updates/EmergencyNumberDbInstallReceiver.java
+++ b/services/core/java/com/android/server/updates/EmergencyNumberDbInstallReceiver.java
@@ -37,9 +37,8 @@
Slog.i(TAG, "Emergency number database is updated in file partition");
// Notify EmergencyNumberTracker for emergency number installation complete.
- Intent notifyInstallComplete = new Intent(
- TelephonyManager.ACTION_OTA_EMERGENCY_NUMBER_DB_INSTALLED);
- context.sendBroadcast(
- notifyInstallComplete, android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
+ TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(
+ Context.TELEPHONY_SERVICE);
+ telephonyManager.notifyOtaEmergencyNumberDbInstalled();
}
}
diff --git a/services/core/java/com/android/server/wm/ActivityDisplay.java b/services/core/java/com/android/server/wm/ActivityDisplay.java
index ebfc65e..be7dfe5 100644
--- a/services/core/java/com/android/server/wm/ActivityDisplay.java
+++ b/services/core/java/com/android/server/wm/ActivityDisplay.java
@@ -1080,6 +1080,8 @@
ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND);
mService.mH.sendMessage(msg);
}
+ mService.mWindowManager.mDisplayNotificationController.dispatchDisplayChanged(
+ this, getConfiguration());
}
return changes;
}
@@ -1408,7 +1410,7 @@
boolean preserveWindows, boolean notifyClients) {
for (int stackNdx = getChildCount() - 1; stackNdx >= 0; --stackNdx) {
final ActivityStack stack = getChildAt(stackNdx);
- stack.ensureActivitiesVisibleLocked(starting, configChanges, preserveWindows,
+ stack.ensureActivitiesVisible(starting, configChanges, preserveWindows,
notifyClients);
}
}
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index f24fa07..e16f3fc 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -121,6 +121,7 @@
import static com.android.server.am.ActivityRecordProto.STATE;
import static com.android.server.am.ActivityRecordProto.TRANSLUCENT;
import static com.android.server.am.ActivityRecordProto.VISIBLE;
+import static com.android.server.am.ActivityRecordProto.VISIBLE_REQUESTED;
import static com.android.server.am.EventLogTags.AM_RELAUNCH_ACTIVITY;
import static com.android.server.am.EventLogTags.AM_RELAUNCH_RESUME_ACTIVITY;
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
@@ -172,11 +173,10 @@
import static com.android.server.wm.ActivityTaskManagerService.getInputDispatchingTimeoutLocked;
import static com.android.server.wm.AppWindowTokenProto.ALL_DRAWN;
import static com.android.server.wm.AppWindowTokenProto.APP_STOPPED;
-import static com.android.server.wm.AppWindowTokenProto.CLIENT_HIDDEN;
+import static com.android.server.wm.AppWindowTokenProto.CLIENT_VISIBLE;
import static com.android.server.wm.AppWindowTokenProto.DEFER_HIDING_CLIENT;
import static com.android.server.wm.AppWindowTokenProto.FILLS_PARENT;
import static com.android.server.wm.AppWindowTokenProto.FROZEN_BOUNDS;
-import static com.android.server.wm.AppWindowTokenProto.HIDDEN_SET_FROM_TRANSFERRED_STARTING_WINDOW;
import static com.android.server.wm.AppWindowTokenProto.IS_ANIMATING;
import static com.android.server.wm.AppWindowTokenProto.IS_WAITING_FOR_TRANSITION_START;
import static com.android.server.wm.AppWindowTokenProto.LAST_ALL_DRAWN;
@@ -190,7 +190,7 @@
import static com.android.server.wm.AppWindowTokenProto.STARTING_MOVED;
import static com.android.server.wm.AppWindowTokenProto.STARTING_WINDOW;
import static com.android.server.wm.AppWindowTokenProto.THUMBNAIL;
-import static com.android.server.wm.AppWindowTokenProto.VISIBLE_REQUESTED;
+import static com.android.server.wm.AppWindowTokenProto.VISIBLE_SET_FROM_TRANSFERRED_STARTING_WINDOW;
import static com.android.server.wm.AppWindowTokenProto.WINDOW_TOKEN;
import static com.android.server.wm.IdentifierProto.HASH_CODE;
import static com.android.server.wm.IdentifierProto.TITLE;
@@ -333,6 +333,9 @@
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
+import java.util.function.Consumer;
+import java.util.function.Function;
+import java.util.function.Predicate;
/**
* An entry in the history stack, representing an activity.
@@ -461,15 +464,16 @@
private boolean keysPaused; // has key dispatching been paused for it?
int launchMode; // the launch mode activity attribute.
int lockTaskLaunchMode; // the lockTaskMode manifest attribute, subject to override
+ private boolean mVisible; // Should this token's windows be visible?
boolean visibleIgnoringKeyguard; // is this activity visible, ignoring the fact that Keyguard
// might hide this activity?
- // True if the hidden state of this token was forced to false due to a transferred starting
+ // True if the visible state of this token was forced to true due to a transferred starting
// window.
- private boolean mHiddenSetFromTransferredStartingWindow;
- // TODO: figureout how to consolidate with the same variable in ActivityRecord.
+ private boolean mVisibleSetFromTransferredStartingWindow;
+ // TODO: figure out how to consolidate with the same variable in ActivityRecord.
private boolean mDeferHidingClient; // If true we told WM to defer reporting to the client
// process that it is hidden.
- private boolean mLastDeferHidingClient; // If true we will defer setting mClientHidden to true
+ private boolean mLastDeferHidingClient; // If true we will defer setting mClientVisible to false
// and reporting to the client that it is hidden.
boolean sleeping; // have we told the activity to sleep?
boolean nowVisible; // is this activity's window visible?
@@ -534,8 +538,8 @@
private Task mLastParent;
- // Have we told the window clients to hide themselves?
- private boolean mClientHidden;
+ // Have we told the window clients to show themselves?
+ private boolean mClientVisible;
boolean firstWindowDrawn;
// Last drawn state we reported to the app token.
@@ -849,13 +853,14 @@
pw.println(requestedVrComponent);
}
super.dump(pw, prefix, dumpAll);
+ pw.print(" visible="); pw.print(mVisible);
if (appToken != null) {
pw.println(prefix + "app=true mVoiceInteraction=" + mVoiceInteraction);
}
pw.print(prefix); pw.print(" mOccludesParent="); pw.print(mOccludesParent);
pw.print(" mOrientation="); pw.println(mOrientation);
pw.println(prefix + "mVisibleRequested=" + mVisibleRequested
- + " mClientHidden=" + mClientHidden
+ + " mClientVisible=" + mClientVisible
+ ((mDeferHidingClient) ? " mDeferHidingClient=" + mDeferHidingClient : "")
+ " reportedDrawn=" + reportedDrawn + " reportedVisible=" + reportedVisible);
if (paused) {
@@ -879,13 +884,13 @@
pw.print(" mIsExiting="); pw.println(mIsExiting);
}
if (startingWindow != null || startingSurface != null
- || startingDisplayed || startingMoved || mHiddenSetFromTransferredStartingWindow) {
+ || startingDisplayed || startingMoved || mVisibleSetFromTransferredStartingWindow) {
pw.print(prefix); pw.print("startingWindow="); pw.print(startingWindow);
pw.print(" startingSurface="); pw.print(startingSurface);
pw.print(" startingDisplayed="); pw.print(startingDisplayed);
pw.print(" startingMoved="); pw.print(startingMoved);
pw.println(" mHiddenSetFromTransferredStartingWindow="
- + mHiddenSetFromTransferredStartingWindow);
+ + mVisibleSetFromTransferredStartingWindow);
}
if (!mFrozenBounds.isEmpty()) {
pw.print(prefix); pw.print("mFrozenBounds="); pw.println(mFrozenBounds);
@@ -1481,7 +1486,7 @@
}
// Application tokens start out hidden.
- setHidden(true);
+ setVisible(false);
mVisibleRequested = false;
ColorDisplayService.ColorDisplayServiceInternal cds = LocalServices.getService(
@@ -1513,6 +1518,7 @@
inHistory = false;
nowVisible = false;
mDrawn = false;
+ mClientVisible = true;
idle = false;
hasBeenLaunched = false;
mStackSupervisor = supervisor;
@@ -1581,6 +1587,12 @@
return this;
}
+ @Override
+ boolean hasActivity() {
+ // I am an activity!
+ return true;
+ }
+
void setProcess(WindowProcessController proc) {
app = proc;
final ActivityRecord root = task != null ? task.getRootActivity() : null;
@@ -3198,7 +3210,7 @@
"Removing starting %s from %s", tStartingWindow, fromActivity);
fromActivity.removeChild(tStartingWindow);
fromActivity.postWindowRemoveStartingWindowCleanup(tStartingWindow);
- fromActivity.mHiddenSetFromTransferredStartingWindow = false;
+ fromActivity.mVisibleSetFromTransferredStartingWindow = false;
addWindow(tStartingWindow);
// Propagate other interesting state between the tokens. If the old token is displayed,
@@ -3211,12 +3223,12 @@
if (fromActivity.firstWindowDrawn) {
firstWindowDrawn = true;
}
- if (!fromActivity.isHidden()) {
- setHidden(false);
+ if (fromActivity.isVisible()) {
+ setVisible(true);
mVisibleRequested = true;
- mHiddenSetFromTransferredStartingWindow = true;
+ mVisibleSetFromTransferredStartingWindow = true;
}
- setClientHidden(fromActivity.mClientHidden);
+ setClientVisible(fromActivity.mClientVisible);
transferAnimation(fromActivity);
@@ -3418,11 +3430,21 @@
}
@Override
- boolean forAllActivities(ToBooleanFunction<ActivityRecord> callback) {
+ boolean forAllActivities(Function<ActivityRecord, Boolean> callback) {
return callback.apply(this);
}
@Override
+ void forAllActivities(Consumer<ActivityRecord> callback, boolean traverseTopToBottom) {
+ callback.accept(this);
+ }
+
+ @Override
+ ActivityRecord getActivity(Predicate<ActivityRecord> callback, boolean traverseTopToBottom) {
+ return callback.test(this) ? this : null;
+ }
+
+ @Override
protected void setLayer(Transaction t, int layer) {
if (!mSurfaceAnimator.hasLeash()) {
t.setLayer(mSurfaceControl, layer);
@@ -3828,7 +3850,14 @@
boolean isVisible() {
// If the activity isn't hidden then it is considered visible and there is no need to check
// its children windows to see if they are visible.
- return !isHidden();
+ return mVisible;
+ }
+
+ void setVisible(boolean visible) {
+ if (visible != mVisible) {
+ mVisible = visible;
+ scheduleAnimation();
+ }
}
void setVisibility(boolean visible) {
@@ -3864,14 +3893,14 @@
// We previously deferred telling the client to hide itself when visibility was
// initially set to false. Now we would like it to hide, so go ahead and set it.
mLastDeferHidingClient = deferHidingClient;
- setClientHidden(true);
+ setClientVisible(false);
}
return;
}
ProtoLog.v(WM_DEBUG_APP_TRANSITIONS,
- "setAppVisibility(%s, visible=%b): %s hidden=%b mVisibleRequested=%b Callers=%s",
- appToken, visible, appTransition, isHidden(), mVisibleRequested,
+ "setAppVisibility(%s, visible=%b): %s visible=%b mVisibleRequested=%b Callers=%s",
+ appToken, visible, appTransition, isVisible(), mVisibleRequested,
Debug.getCallers(6));
final DisplayContent displayContent = getDisplayContent();
@@ -3901,15 +3930,15 @@
startingMoved = false;
// If the token is currently hidden (should be the common case), or has been
// stopped, then we need to set up to wait for its windows to be ready.
- if (isHidden() || mAppStopped) {
+ if (!isVisible() || mAppStopped) {
clearAllDrawn();
// If the app was already visible, don't reset the waitingToShow state.
- if (isHidden()) {
+ if (!isVisible()) {
waitingToShow = true;
// If the client isn't hidden, we don't need to reset the drawing state.
- if (isClientHidden()) {
+ if (!isClientVisible()) {
// Let's reset the draw state in order to prevent the starting window to be
// immediately dismissed when the app still has the surface.
forAllWindows(w -> {
@@ -3929,7 +3958,7 @@
// we still need to tell the client to make its windows visible so they get drawn.
// Otherwise, we will wait on performing the transition until all windows have been
// drawn, they never will be, and we are sad.
- setClientHidden(false);
+ setClientVisible(true);
requestUpdateWallpaperIfNeeded();
@@ -3975,9 +4004,9 @@
boolean visible, int transit, boolean performLayout, boolean isVoiceInteraction) {
boolean delayed = false;
- // Reset the state of mHiddenSetFromTransferredStartingWindow since visibility is actually
+ // Reset the state of mVisibleSetFromTransferredStartingWindow since visibility is actually
// been set by the app now.
- mHiddenSetFromTransferredStartingWindow = false;
+ mVisibleSetFromTransferredStartingWindow = false;
// Allow for state changes and animation to be applied if:
// * token is transitioning visibility state
@@ -3987,7 +4016,7 @@
// * or the token is the opening app and visible while opening task behind existing one.
final DisplayContent displayContent = getDisplayContent();
boolean visibilityChanged = false;
- if (isHidden() == visible || (isHidden() && mIsExiting)
+ if (isVisible() != visible || (!isVisible() && mIsExiting)
|| (visible && waitingForReplacement())
|| (visible && displayContent.mOpeningApps.contains(this)
&& displayContent.mAppTransition.getAppTransition() == TRANSIT_TASK_OPEN_BEHIND)) {
@@ -3995,7 +4024,7 @@
mWmService.mAccessibilityController;
boolean changed = false;
ProtoLog.v(WM_DEBUG_APP_TRANSITIONS,
- "Changing app %s hidden=%b performLayout=%b", this, isHidden(),
+ "Changing app %s visible=%b performLayout=%b", this, isVisible(),
performLayout);
boolean runningAppAnimation = false;
@@ -4020,7 +4049,7 @@
changed |= win.onAppVisibilityChanged(visible, runningAppAnimation);
}
- setHidden(!visible);
+ setVisible(visible);
mVisibleRequested = visible;
visibilityChanged = true;
if (!visible) {
@@ -4039,8 +4068,8 @@
}
ProtoLog.v(WM_DEBUG_APP_TRANSITIONS,
- "commitVisibility: %s: hidden=%b visibleRequested=%b", this,
- isHidden(), mVisibleRequested);
+ "commitVisibility: %s: visible=%b visibleRequested=%b", this,
+ isVisible(), mVisibleRequested);
if (changed) {
displayContent.getInputMonitor().setUpdateInputWindowsNeededLw();
@@ -4077,7 +4106,7 @@
// If we're becoming invisible, update the client visibility if we are not running an
// animation. Otherwise, we'll update client visibility in onAnimationFinished.
if (visible || !isAnimating()) {
- setClientHidden(!visible);
+ setClientVisible(visible);
}
if (!displayContent.mClosingApps.contains(this)
@@ -4104,7 +4133,7 @@
// no animation but there will still be a transition set.
// We still need to delay hiding the surface such that it
// can be synchronized with showing the next surface in the transition.
- if (isHidden() && !delayed && !displayContent.mAppTransition.isTransitionSet()) {
+ if (!isVisible() && !delayed && !displayContent.mAppTransition.isTransitionSet()) {
SurfaceControl.openTransaction();
for (int i = mChildren.size() - 1; i >= 0; i--) {
mChildren.get(i).mWinAnimator.hide("immediately hidden");
@@ -4116,12 +4145,6 @@
return delayed;
}
- @Override
- void setHidden(boolean hidden) {
- super.setHidden(hidden);
- scheduleAnimation();
- }
-
/**
* See {@link Activity#setDisablePreviewScreenshots}.
*/
@@ -4550,7 +4573,7 @@
// If the activity is stopped, stopping, cycle to an active state. We avoid doing
// this when there is an activity waiting to become translucent as the extra binder
// calls will lead to noticeable jank. A later call to
- // ActivityStack#ensureActivitiesVisibleLocked will bring the activity to a proper
+ // ActivityStack#ensureActivitiesVisible will bring the activity to a proper
// active state.
if (!isState(STARTED, RESUMED, PAUSED, STOPPED, STOPPING)
|| getActivityStack().mTranslucentActivityWaiting != null) {
@@ -4882,8 +4905,8 @@
void startFreezingScreen() {
ProtoLog.i(WM_DEBUG_ORIENTATION,
- "Set freezing of %s: hidden=%b freezing=%b visibleRequested=%b. %s",
- appToken, isHidden(), mFreezingScreen, mVisibleRequested,
+ "Set freezing of %s: visible=%b freezing=%b visibleRequested=%b. %s",
+ appToken, isVisible(), mFreezingScreen, mVisibleRequested,
new RuntimeException().fillInStackTrace());
if (mVisibleRequested) {
if (!mFreezingScreen) {
@@ -4921,8 +4944,8 @@
return;
}
ProtoLog.v(WM_DEBUG_ORIENTATION,
- "Clear freezing of %s: hidden=%b freezing=%b", appToken,
- isHidden(), isFreezingScreen());
+ "Clear freezing of %s: visible=%b freezing=%b", appToken,
+ isVisible(), isFreezingScreen());
stopFreezingScreen(true, force);
}
}
@@ -5082,7 +5105,7 @@
boolean nowGone = mReportedVisibilityResults.nowGone;
boolean nowDrawn = numInteresting > 0 && numDrawn >= numInteresting;
- boolean nowVisible = numInteresting > 0 && numVisible >= numInteresting && !isHidden();
+ boolean nowVisible = numInteresting > 0 && numVisible >= numInteresting && isVisible();
if (!nowGone) {
// If the app is not yet gone, then it can only become visible/drawn.
if (!nowDrawn) {
@@ -5110,18 +5133,18 @@
}
}
- boolean isClientHidden() {
- return mClientHidden;
+ boolean isClientVisible() {
+ return mClientVisible;
}
- void setClientHidden(boolean hideClient) {
- if (mClientHidden == hideClient || (hideClient && mDeferHidingClient)) {
+ void setClientVisible(boolean clientVisible) {
+ if (mClientVisible == clientVisible || (!clientVisible && mDeferHidingClient)) {
return;
}
ProtoLog.v(WM_DEBUG_APP_TRANSITIONS,
- "setClientHidden: %s clientHidden=%b Callers=%s", this, hideClient,
+ "setClientVisible: %s clientVisible=%b Callers=%s", this, clientVisible,
Debug.getCallers(5));
- mClientHidden = hideClient;
+ mClientVisible = clientVisible;
sendAppVisibilityToClients();
}
@@ -5443,11 +5466,11 @@
// well there is no point now.
ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Nulling last startingData");
mStartingData = null;
- if (mHiddenSetFromTransferredStartingWindow) {
- // We set the hidden state to false for the token from a transferred starting window.
- // We now reset it back to true since the starting window was the last window in the
- // token.
- setHidden(true);
+ if (mVisibleSetFromTransferredStartingWindow) {
+ // We set the visible state to true for the token from a transferred starting
+ // window. We now reset it back to false since the starting window was the last
+ // window in the token.
+ setVisible(false);
}
} else if (mChildren.size() == 1 && startingSurface != null && !isRelaunching()) {
// If this is the last window except for a starting transition window,
@@ -5785,7 +5808,7 @@
@Override
void prepareSurfaces() {
- final boolean show = !isHidden() || isAnimating();
+ final boolean show = isVisible() || isAnimating();
if (mSurfaceControl != null) {
if (show && !mLastSurfaceShowing) {
@@ -5904,7 +5927,7 @@
"AppWindowToken");
clearThumbnail();
- setClientHidden(isHidden() && !mVisibleRequested);
+ setClientVisible(isVisible() || mVisibleRequested);
getDisplayContent().computeImeTargetIfNeeded(this);
@@ -6216,9 +6239,6 @@
// relatively fixed.
overrideConfig.colorMode = fullConfig.colorMode;
overrideConfig.densityDpi = fullConfig.densityDpi;
- overrideConfig.screenLayout = fullConfig.screenLayout
- & (Configuration.SCREENLAYOUT_LONG_MASK
- | Configuration.SCREENLAYOUT_SIZE_MASK);
// The smallest screen width is the short side of screen bounds. Because the bounds
// and density won't be changed, smallestScreenWidthDp is also fixed.
overrideConfig.smallestScreenWidthDp = fullConfig.smallestScreenWidthDp;
@@ -6353,6 +6373,10 @@
// Use resolvedBounds to compute other override configurations such as appBounds
task.computeConfigResourceOverrides(resolvedConfig, newParentConfiguration,
mCompatDisplayInsets);
+ // Use current screen layout as source because the size of app is independent to parent.
+ resolvedConfig.screenLayout = Task.computeScreenLayoutOverride(
+ getConfiguration().screenLayout, resolvedConfig.screenWidthDp,
+ resolvedConfig.screenHeightDp);
// Use parent orientation if it cannot be decided by bounds, so the activity can fit inside
// the parent bounds appropriately.
@@ -7287,12 +7311,13 @@
writeToProto(proto, APP_WINDOW_TOKEN, WindowTraceLogLevel.ALL);
writeIdentifierToProto(proto, IDENTIFIER);
proto.write(STATE, mState.toString());
- proto.write(VISIBLE, mVisibleRequested);
+ proto.write(VISIBLE_REQUESTED, mVisibleRequested);
proto.write(FRONT_OF_TASK, isRootOfTask());
if (hasProcess()) {
proto.write(PROC_ID, app.getPid());
}
proto.write(TRANSLUCENT, !occludesParent());
+ proto.write(VISIBLE, mVisible);
}
public void writeToProto(ProtoOutputStream proto, long fieldId) {
@@ -7323,8 +7348,8 @@
}
proto.write(FILLS_PARENT, mOccludesParent);
proto.write(APP_STOPPED, mAppStopped);
- proto.write(VISIBLE_REQUESTED, mVisibleRequested);
- proto.write(CLIENT_HIDDEN, mClientHidden);
+ proto.write(com.android.server.wm.AppWindowTokenProto.VISIBLE_REQUESTED, mVisibleRequested);
+ proto.write(CLIENT_VISIBLE, mClientVisible);
proto.write(DEFER_HIDING_CLIENT, mDeferHidingClient);
proto.write(REPORTED_DRAWN, reportedDrawn);
proto.write(REPORTED_VISIBLE, reportedVisible);
@@ -7337,11 +7362,12 @@
}
proto.write(STARTING_DISPLAYED, startingDisplayed);
proto.write(STARTING_MOVED, startingMoved);
- proto.write(HIDDEN_SET_FROM_TRANSFERRED_STARTING_WINDOW,
- mHiddenSetFromTransferredStartingWindow);
+ proto.write(VISIBLE_SET_FROM_TRANSFERRED_STARTING_WINDOW,
+ mVisibleSetFromTransferredStartingWindow);
for (Rect bounds : mFrozenBounds) {
bounds.writeToProto(proto, FROZEN_BOUNDS);
}
+ proto.write(com.android.server.wm.AppWindowTokenProto.VISIBLE, mVisible);
proto.end(token);
}
diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java
index ac94125..f1c47eb 100644
--- a/services/core/java/com/android/server/wm/ActivityStack.java
+++ b/services/core/java/com/android/server/wm/ActivityStack.java
@@ -62,7 +62,6 @@
import static com.android.server.am.ActivityStackProto.FULLSCREEN;
import static com.android.server.am.ActivityStackProto.RESUMED_ACTIVITY;
import static com.android.server.am.ActivityStackProto.STACK;
-import static com.android.server.wm.ActivityRecord.FINISH_RESULT_REMOVED;
import static com.android.server.wm.ActivityStack.ActivityState.PAUSED;
import static com.android.server.wm.ActivityStack.ActivityState.PAUSING;
import static com.android.server.wm.ActivityStack.ActivityState.RESUMED;
@@ -119,7 +118,6 @@
import static com.android.server.wm.StackProto.FILLS_PARENT;
import static com.android.server.wm.StackProto.MINIMIZE_AMOUNT;
import static com.android.server.wm.StackProto.WINDOW_CONTAINER;
-import static com.android.server.wm.Task.REPARENT_LEAVE_STACK_IN_PLACE;
import static com.android.server.wm.WindowContainer.AnimationFlags.CHILDREN;
import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_MOVEMENT;
@@ -203,7 +201,7 @@
class ActivityStack extends WindowContainer<Task> implements BoundsAnimationTarget,
ConfigurationContainerListener {
private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityStack" : TAG_ATM;
- private static final String TAG_ADD_REMOVE = TAG + POSTFIX_ADD_REMOVE;
+ static final String TAG_ADD_REMOVE = TAG + POSTFIX_ADD_REMOVE;
private static final String TAG_APP = TAG + POSTFIX_APP;
private static final String TAG_CLEANUP = TAG + POSTFIX_CLEANUP;
private static final String TAG_PAUSE = TAG + POSTFIX_PAUSE;
@@ -212,10 +210,10 @@
private static final String TAG_STACK = TAG + POSTFIX_STACK;
private static final String TAG_STATES = TAG + POSTFIX_STATES;
private static final String TAG_SWITCH = TAG + POSTFIX_SWITCH;
- private static final String TAG_TASKS = TAG + POSTFIX_TASKS;
+ static final String TAG_TASKS = TAG + POSTFIX_TASKS;
private static final String TAG_TRANSITION = TAG + POSTFIX_TRANSITION;
private static final String TAG_USER_LEAVING = TAG + POSTFIX_USER_LEAVING;
- private static final String TAG_VISIBILITY = TAG + POSTFIX_VISIBILITY;
+ static final String TAG_VISIBILITY = TAG + POSTFIX_VISIBILITY;
// Ticks during which we check progress while waiting for an app to launch.
private static final int LAUNCH_TICK = 500;
@@ -516,6 +514,10 @@
}
}
+ private static final ResetTargetTaskHelper sResetTargetTaskHelper = new ResetTargetTaskHelper();
+ private final EnsureActivitiesVisibleHelper mEnsureActivitiesVisibleHelper =
+ new EnsureActivitiesVisibleHelper(this);
+
int numActivities() {
int count = 0;
for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
@@ -1492,8 +1494,7 @@
void goToSleep() {
// Ensure visibility without updating configuration, as activities are about to sleep.
- ensureActivitiesVisibleLocked(null /* starting */, 0 /* configChanges */,
- !PRESERVE_WINDOWS);
+ ensureActivitiesVisible(null /* starting */, 0 /* configChanges */, !PRESERVE_WINDOWS);
// Make sure any paused or stopped but visible activities are now sleeping.
// This ensures that the activity's onStop() is called.
@@ -1979,127 +1980,25 @@
* Make sure that all activities that need to be visible in the stack (that is, they
* currently can be seen by the user) actually are and update their configuration.
*/
- final void ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges,
+ void ensureActivitiesVisible(ActivityRecord starting, int configChanges,
boolean preserveWindows) {
- ensureActivitiesVisibleLocked(starting, configChanges, preserveWindows,
- true /* notifyClients */);
+ ensureActivitiesVisible(starting, configChanges, preserveWindows, true /* notifyClients */);
}
/**
* Ensure visibility with an option to also update the configuration of visible activities.
- * @see #ensureActivitiesVisibleLocked(ActivityRecord, int, boolean)
+ * @see #ensureActivitiesVisible(ActivityRecord, int, boolean)
* @see RootActivityContainer#ensureActivitiesVisible(ActivityRecord, int, boolean)
*/
// TODO: Should be re-worked based on the fact that each task as a stack in most cases.
- final void ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges,
+ void ensureActivitiesVisible(ActivityRecord starting, int configChanges,
boolean preserveWindows, boolean notifyClients) {
mTopActivityOccludesKeyguard = false;
mTopDismissingKeyguardActivity = null;
mStackSupervisor.getKeyguardController().beginActivityVisibilityUpdate();
try {
- ActivityRecord top = topRunningActivityLocked();
- if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "ensureActivitiesVisible behind " + top
- + " configChanges=0x" + Integer.toHexString(configChanges));
- if (top != null) {
- checkTranslucentActivityWaiting(top);
- }
-
- // If the top activity is not fullscreen, then we need to
- // make sure any activities under it are now visible.
- boolean aboveTop = top != null;
- final boolean stackShouldBeVisible = shouldBeVisible(starting);
- boolean behindFullscreenActivity = !stackShouldBeVisible;
- // We should not resume activities that being launched behind because these
- // activities are actually behind other fullscreen activities, but still required
- // to be visible (such as performing Recents animation).
- final boolean resumeTopActivity = isFocusable() && isInStackLocked(starting) == null
- && top != null && !top.mLaunchTaskBehind;
- for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
- final Task task = getChildAt(taskNdx);
- for (int activityNdx = task.getChildCount() - 1; activityNdx >= 0; --activityNdx) {
- final ActivityRecord r = task.getChildAt(activityNdx);
- final boolean isTop = r == top;
- if (aboveTop && !isTop) {
- continue;
- }
- aboveTop = false;
-
- final boolean reallyVisible = r.shouldBeVisible(behindFullscreenActivity,
- false /* ignoringKeyguard */);
- // Check whether activity should be visible without Keyguard influence
- if (r.visibleIgnoringKeyguard) {
- if (r.occludesParent()) {
- // At this point, nothing else needs to be shown in this task.
- if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Fullscreen: at " + r
- + " stackVisible=" + stackShouldBeVisible
- + " behindFullscreen=" + behindFullscreenActivity);
- behindFullscreenActivity = true;
- } else {
- behindFullscreenActivity = false;
- }
- }
-
- if (reallyVisible) {
- if (r.finishing) {
- continue;
- }
- if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Make visible? " + r
- + " finishing=" + r.finishing + " state=" + r.getState());
- // First: if this is not the current activity being started, make
- // sure it matches the current configuration.
- if (r != starting && notifyClients) {
- r.ensureActivityConfiguration(0 /* globalChanges */, preserveWindows,
- true /* ignoreVisibility */);
- }
-
- if (!r.attachedToProcess()) {
- makeVisibleAndRestartIfNeeded(starting, configChanges, isTop,
- resumeTopActivity && isTop, r);
- } else if (r.mVisibleRequested) {
- // If this activity is already visible, then there is nothing to do here.
- if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY,
- "Skipping: already visible at " + r);
-
- if (r.mClientVisibilityDeferred && notifyClients) {
- r.makeClientVisible();
- }
-
- r.handleAlreadyVisible();
- if (notifyClients) {
- r.makeActiveIfNeeded(starting);
- }
- } else {
- r.makeVisibleIfNeeded(starting, notifyClients);
- }
- // Aggregate current change flags.
- configChanges |= r.configChangeFlags;
- } else {
- if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Make invisible? " + r
- + " finishing=" + r.finishing + " state=" + r.getState()
- + " stackShouldBeVisible=" + stackShouldBeVisible
- + " behindFullscreenActivity=" + behindFullscreenActivity
- + " mLaunchTaskBehind=" + r.mLaunchTaskBehind);
- r.makeInvisible();
- }
- }
- final int windowingMode = getWindowingMode();
- if (windowingMode == WINDOWING_MODE_FREEFORM) {
- // The visibility of tasks and the activities they contain in freeform stack are
- // determined individually unlike other stacks where the visibility or fullscreen
- // status of an activity in a previous task affects other.
- behindFullscreenActivity = !stackShouldBeVisible;
- } else if (isActivityTypeHome()) {
- if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Home task: at " + task
- + " stackShouldBeVisible=" + stackShouldBeVisible
- + " behindFullscreenActivity=" + behindFullscreenActivity);
- // No other task in the home stack should be visible behind the home activity.
- // Home activities is usually a translucent activity with the wallpaper behind
- // them. However, when they don't have the wallpaper behind them, we want to
- // show activities in the next application stack behind them vs. another
- // task in the home stack like recents.
- behindFullscreenActivity = true;
- }
- }
+ mEnsureActivitiesVisibleHelper.process(
+ starting, configChanges, preserveWindows, notifyClients);
if (mTranslucentActivityWaiting != null &&
mUndrawnActivitiesBelowTopTranslucent.isEmpty()) {
@@ -2214,7 +2113,7 @@
return (flags & FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD) != 0;
}
- private void checkTranslucentActivityWaiting(ActivityRecord top) {
+ void checkTranslucentActivityWaiting(ActivityRecord top) {
if (mTranslucentActivityWaiting != top) {
mUndrawnActivitiesBelowTopTranslucent.clear();
if (mTranslucentActivityWaiting != null) {
@@ -2226,31 +2125,6 @@
}
}
- private boolean makeVisibleAndRestartIfNeeded(ActivityRecord starting, int configChanges,
- boolean isTop, boolean andResume, ActivityRecord r) {
- // We need to make sure the app is running if it's the top, or it is just made visible from
- // invisible. If the app is already visible, it must have died while it was visible. In this
- // case, we'll show the dead window but will not restart the app. Otherwise we could end up
- // thrashing.
- if (isTop || !r.mVisibleRequested) {
- // This activity needs to be visible, but isn't even running...
- // get it started and resume if no other stack in this stack is resumed.
- if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Start and freeze screen for " + r);
- if (r != starting) {
- r.startFreezingScreenLocked(configChanges);
- }
- if (!r.mVisibleRequested || r.mLaunchTaskBehind) {
- if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Starting and making visible: " + r);
- r.setVisibility(true);
- }
- if (r != starting) {
- mStackSupervisor.startSpecificActivityLocked(r, andResume, true /* checkConfig */);
- return true;
- }
- }
- return false;
- }
-
void convertActivityToTranslucent(ActivityRecord r) {
mTranslucentActivityWaiting = r;
mUndrawnActivitiesBelowTopTranslucent.clear();
@@ -2490,7 +2364,7 @@
&& next.containsDismissKeyguardWindow();
if (canShowWhenLocked || mayDismissKeyguard) {
- ensureActivitiesVisibleLocked(null /* starting */, 0 /* configChanges */,
+ ensureActivitiesVisible(null /* starting */, 0 /* configChanges */,
!PRESERVE_WINDOWS);
nothingToResume = shouldSleepActivities();
}
@@ -2819,7 +2693,7 @@
next.showStartingWindow(null /* prev */, false /* newTask */,
false /* taskSwitch */);
}
- mStackSupervisor.startSpecificActivityLocked(next, true, false);
+ mStackSupervisor.startSpecificActivity(next, true, false);
return true;
}
@@ -2846,7 +2720,7 @@
if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Restarting: " + next);
}
if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: Restarting " + next);
- mStackSupervisor.startSpecificActivityLocked(next, true, true);
+ mStackSupervisor.startSpecificActivity(next, true, true);
}
return true;
@@ -2980,7 +2854,7 @@
// If the caller has requested that the target task be
// reset, then do so.
if ((r.intent.getFlags() & Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
- resetTaskIfNeededLocked(r, r);
+ resetTaskIfNeeded(r, r);
doShow = topRunningNonDelayedActivityLocked(null) == r;
}
} else if (options != null && options.getAnimationType()
@@ -2991,7 +2865,7 @@
// Don't do a starting window for mLaunchTaskBehind. More importantly make sure we
// tell WindowManager that r is visible even though it is at the back of the stack.
r.setVisibility(true);
- ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
+ ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
// Go ahead to execute app transition for this activity since the app transition
// will not be triggered through the resume channel.
getDisplay().mDisplayContent.executeAppTransition();
@@ -3052,297 +2926,6 @@
}
/**
- * Helper method for {@link #resetTaskIfNeededLocked(ActivityRecord, ActivityRecord)}.
- * Performs a reset of the given task, if needed for new activity start.
- * @param task The task containing the Activity (taskTop) that might be reset.
- * @param forceReset Flag indicating if clear task was requested
- * @return An ActivityOptions that needs to be processed.
- */
- private ActivityOptions resetTargetTaskIfNeededLocked(Task task, boolean forceReset) {
- ActivityOptions topOptions = null;
-
- // Tracker of the end of currently handled reply chain (sublist) of activities. What happens
- // to activities in the same chain will depend on what the end activity of the chain needs.
- int replyChainEnd = -1;
- boolean canMoveOptions = true;
- int numTasksCreated = 0;
-
- // We only do this for activities that are not the root of the task (since if we finish
- // the root, we may no longer have the task!).
- final int numActivities = task.getChildCount();
- int lastActivityNdx = task.findRootIndex(true /* effectiveRoot */);
- if (lastActivityNdx == -1) {
- lastActivityNdx = 0;
- }
- for (int i = numActivities - 1; i > lastActivityNdx; --i) {
- ActivityRecord target = task.getChildAt(i);
- // TODO: Why is this needed? Looks like we're breaking the loop before we reach the root
- if (target.isRootOfTask()) break;
-
- final int flags = target.info.flags;
- final boolean finishOnTaskLaunch =
- (flags & ActivityInfo.FLAG_FINISH_ON_TASK_LAUNCH) != 0;
- final boolean allowTaskReparenting =
- (flags & ActivityInfo.FLAG_ALLOW_TASK_REPARENTING) != 0;
- final boolean clearWhenTaskReset =
- (target.intent.getFlags() & Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0;
-
- if (!finishOnTaskLaunch
- && !clearWhenTaskReset
- && target.resultTo != null) {
- // If this activity is sending a reply to a previous
- // activity, we can't do anything with it now until
- // we reach the start of the reply chain.
- // XXX note that we are assuming the result is always
- // to the previous activity, which is almost always
- // the case but we really shouldn't count on.
- if (replyChainEnd < 0) {
- replyChainEnd = i;
- }
- } else if (!finishOnTaskLaunch
- && !clearWhenTaskReset
- && allowTaskReparenting
- && target.taskAffinity != null
- && !target.taskAffinity.equals(task.affinity)) {
- // If this activity has an affinity for another
- // task, then we need to move it out of here. We will
- // move it as far out of the way as possible, to the
- // bottom of the activity stack. This also keeps it
- // correctly ordered with any activities we previously
- // moved.
- // TODO: We should probably look for other stacks also, since corresponding task
- // with the same affinity is unlikely to be in the same stack.
- final Task targetTask;
- final ActivityRecord bottom =
- hasChild() && getChildAt(0).hasChild() ?
- getChildAt(0).getChildAt(0) : null;
- if (bottom != null && target.taskAffinity.equals(bottom.getTask().affinity)) {
- // If the activity currently at the bottom has the
- // same task affinity as the one we are moving,
- // then merge it into the same task.
- targetTask = bottom.getTask();
- if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Start pushing activity " + target
- + " out to bottom task " + targetTask);
- } else {
- targetTask = createTask(
- mStackSupervisor.getNextTaskIdForUserLocked(target.mUserId),
- target.info, null /* intent */, null /* voiceSession */,
- null /* voiceInteractor */, false /* toTop */);
- targetTask.affinityIntent = target.intent;
- numTasksCreated++;
- if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Start pushing activity " + target
- + " out to new task " + targetTask);
- }
-
- boolean noOptions = canMoveOptions;
- final int start = replyChainEnd < 0 ? i : replyChainEnd;
- for (int srcPos = start; srcPos >= i; --srcPos) {
- final ActivityRecord p = task.getChildAt(srcPos);
- if (p.finishing) {
- continue;
- }
-
- canMoveOptions = false;
- if (noOptions && topOptions == null) {
- topOptions = p.takeOptionsLocked(false /* fromClient */);
- if (topOptions != null) {
- noOptions = false;
- }
- }
- if (DEBUG_ADD_REMOVE) Slog.i(TAG_ADD_REMOVE,
- "Removing activity " + p + " from task=" + task + " adding to task="
- + targetTask + " Callers=" + Debug.getCallers(4));
- if (DEBUG_TASKS) Slog.v(TAG_TASKS,
- "Pushing next activity " + p + " out to target's task " + target);
- p.reparent(targetTask, 0 /* position - bottom */, "resetTargetTaskIfNeeded");
- }
-
- positionChildAtBottom(targetTask);
- mStackSupervisor.mRecentTasks.add(targetTask);
- replyChainEnd = -1;
- } else if (forceReset || finishOnTaskLaunch || clearWhenTaskReset) {
- // If the activity should just be removed -- either
- // because it asks for it, or the task should be
- // cleared -- then finish it and anything that is
- // part of its reply chain.
- int end;
- if (clearWhenTaskReset) {
- // In this case, we want to finish this activity
- // and everything above it, so be sneaky and pretend
- // like these are all in the reply chain.
- end = task.getChildCount() - 1;
- } else if (replyChainEnd < 0) {
- end = i;
- } else {
- end = replyChainEnd;
- }
- boolean noOptions = canMoveOptions;
- for (int srcPos = i; srcPos <= end; srcPos++) {
- ActivityRecord p = task.getChildAt(srcPos);
- if (p.finishing) {
- continue;
- }
- canMoveOptions = false;
- if (noOptions && topOptions == null) {
- topOptions = p.takeOptionsLocked(false /* fromClient */);
- if (topOptions != null) {
- noOptions = false;
- }
- }
- if (DEBUG_TASKS) Slog.w(TAG_TASKS,
- "resetTaskIntendedTask: calling finishActivity on " + p);
- if (p.finishIfPossible("reset-task", false /* oomAdj */)
- == FINISH_RESULT_REMOVED) {
- end--;
- srcPos--;
- }
- }
- replyChainEnd = -1;
- } else {
- // If we were in the middle of a chain, well the
- // activity that started it all doesn't want anything
- // special, so leave it all as-is.
- replyChainEnd = -1;
- }
- }
-
- // Create target stack for the newly created tasks if necessary
- if (numTasksCreated > 0) {
- ActivityDisplay display = getDisplay();
- final boolean singleTaskInstanceDisplay = display.isSingleTaskInstance();
- if (singleTaskInstanceDisplay) {
- display = mRootActivityContainer.getDefaultDisplay();
- }
-
- if (singleTaskInstanceDisplay || display.alwaysCreateStack(getWindowingMode(),
- getActivityType())) {
- for (int index = numTasksCreated - 1; index >= 0; index--) {
- final Task targetTask = getChildAt(index);
- final ActivityStack targetStack = display.getOrCreateStack(getWindowingMode(),
- getActivityType(), false /* onTop */);
- targetTask.reparent(targetStack, false /* toTop */,
- REPARENT_LEAVE_STACK_IN_PLACE, false /* animate */,
- true /* deferResume */, "resetTargetTask");
- }
- }
- }
-
- return topOptions;
- }
-
- /**
- * Helper method for {@link #resetTaskIfNeededLocked(ActivityRecord, ActivityRecord)}.
- * Processes all of the activities in a given Task looking for an affinity with the task
- * of resetTaskIfNeededLocked.taskTop.
- * @param affinityTask The task we are looking for an affinity to.
- * @param task Task that resetTaskIfNeededLocked.taskTop belongs to.
- * @param topTaskIsHigher True if #task has already been processed by resetTaskIfNeededLocked.
- * @param forceReset Flag indicating if clear task was requested
- */
- // TODO: Consider merging with #resetTargetTaskIfNeededLocked() above
- private int resetAffinityTaskIfNeededLocked(Task affinityTask, Task task,
- boolean topTaskIsHigher, boolean forceReset, int taskInsertionPoint) {
- // Tracker of the end of currently handled reply chain (sublist) of activities. What happens
- // to activities in the same chain will depend on what the end activity of the chain needs.
- int replyChainEnd = -1;
- final String taskAffinity = task.affinity;
-
- final int numActivities = task.getChildCount();
-
- // Do not operate on or below the effective root Activity.
- int lastActivityNdx = affinityTask.findRootIndex(true /* effectiveRoot */);
- if (lastActivityNdx == -1) {
- lastActivityNdx = 0;
- }
- for (int i = numActivities - 1; i > lastActivityNdx; --i) {
- ActivityRecord target = task.getChildAt(i);
- // TODO: Why is this needed? Looks like we're breaking the loop before we reach the root
- if (target.isRootOfTask()) break;
-
- final int flags = target.info.flags;
- boolean finishOnTaskLaunch = (flags & ActivityInfo.FLAG_FINISH_ON_TASK_LAUNCH) != 0;
- boolean allowTaskReparenting = (flags & ActivityInfo.FLAG_ALLOW_TASK_REPARENTING) != 0;
-
- if (target.resultTo != null) {
- // If this activity is sending a reply to a previous
- // activity, we can't do anything with it now until
- // we reach the start of the reply chain.
- // XXX note that we are assuming the result is always
- // to the previous activity, which is almost always
- // the case but we really shouldn't count on.
- if (replyChainEnd < 0) {
- replyChainEnd = i;
- }
- } else if (topTaskIsHigher
- && allowTaskReparenting
- && taskAffinity != null
- && taskAffinity.equals(target.taskAffinity)) {
- // This activity has an affinity for our task. Either remove it if we are
- // clearing or move it over to our task. Note that
- // we currently punt on the case where we are resetting a
- // task that is not at the top but who has activities above
- // with an affinity to it... this is really not a normal
- // case, and we will need to later pull that task to the front
- // and usually at that point we will do the reset and pick
- // up those remaining activities. (This only happens if
- // someone starts an activity in a new task from an activity
- // in a task that is not currently on top.)
- if (forceReset || finishOnTaskLaunch) {
- final int start = replyChainEnd >= 0 ? replyChainEnd : i;
- if (DEBUG_TASKS) Slog.v(TAG_TASKS,
- "Finishing task at index " + start + " to " + i);
- for (int srcPos = start; srcPos >= i; --srcPos) {
- final ActivityRecord p = task.getChildAt(srcPos);
- if (p.finishing) {
- continue;
- }
- p.finishIfPossible("move-affinity", false /* oomAdj */);
- }
- } else {
- if (taskInsertionPoint < 0) {
- taskInsertionPoint = task.getChildCount();
-
- }
-
- final int start = replyChainEnd >= 0 ? replyChainEnd : i;
- if (DEBUG_TASKS) Slog.v(TAG_TASKS,
- "Reparenting from task=" + affinityTask + ":" + start + "-" + i
- + " to task=" + task + ":" + taskInsertionPoint);
- for (int srcPos = start; srcPos >= i; --srcPos) {
- final ActivityRecord p = task.getChildAt(srcPos);
- p.reparent(task, taskInsertionPoint, "resetAffinityTaskIfNeededLocked");
-
- if (DEBUG_ADD_REMOVE) Slog.i(TAG_ADD_REMOVE,
- "Removing and adding activity " + p + " to stack at " + task
- + " callers=" + Debug.getCallers(3));
- if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Pulling activity " + p
- + " from " + srcPos + " in to resetting task " + task);
- }
- positionChildAtTop(task);
-
- // Now we've moved it in to place... but what if this is
- // a singleTop activity and we have put it on top of another
- // instance of the same activity? Then we drop the instance
- // below so it remains singleTop.
- if (target.info.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP) {
- final ArrayList<ActivityRecord> taskActivities = task.mChildren;
- final int targetNdx = taskActivities.indexOf(target);
- if (targetNdx > 0) {
- final ActivityRecord p = taskActivities.get(targetNdx - 1);
- if (p.intent.getComponent().equals(target.intent.getComponent())) {
- p.finishIfPossible("replace", false /* oomAdj */);
- }
- }
- }
- }
-
- replyChainEnd = -1;
- }
- }
- return taskInsertionPoint;
- }
-
- /**
* Reset the task by reparenting the activities that have same affinity to the task or
* reparenting the activities that have different affinityies out of the task, while these
* activities allow task reparenting.
@@ -3352,37 +2935,16 @@
* @return The non-finishing top activity of the task after reset or the original task top
* activity if all activities within the task are finishing.
*/
- final ActivityRecord resetTaskIfNeededLocked(ActivityRecord taskTop,
- ActivityRecord newActivity) {
+ ActivityRecord resetTaskIfNeeded(ActivityRecord taskTop, ActivityRecord newActivity) {
final boolean forceReset =
(newActivity.info.flags & ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0;
final Task task = taskTop.getTask();
- // False until we evaluate the Task associated with taskTop. Switches to true
- // for remaining tasks. Used for later tasks to reparent to task.
- boolean taskFound = false;
-
// If ActivityOptions are moved out and need to be aborted or moved to taskTop.
- ActivityOptions topOptions = null;
+ final ActivityOptions topOptions = sResetTargetTaskHelper.process(this, task, forceReset);
- // Preserve the location for reparenting in the new task.
- int reparentInsertionPoint = -1;
-
- for (int i = getChildCount() - 1; i >= 0; --i) {
- final Task targetTask = getChildAt(i);
-
- if (targetTask == task) {
- topOptions = resetTargetTaskIfNeededLocked(task, forceReset);
- taskFound = true;
- } else {
- reparentInsertionPoint = resetAffinityTaskIfNeededLocked(targetTask, task,
- taskFound, forceReset, reparentInsertionPoint);
- }
- }
-
- int taskNdx = mChildren.indexOf(task);
- if (taskNdx >= 0) {
- ActivityRecord newTop = getChildAt(taskNdx).getTopNonFinishingActivity();
+ if (mChildren.contains(task)) {
+ final ActivityRecord newTop = task.getTopNonFinishingActivity();
if (newTop != null) {
taskTop = newTop;
}
@@ -3391,11 +2953,7 @@
if (topOptions != null) {
// If we got some ActivityOptions from an activity on top that
// was removed from the task, propagate them to the new real top.
- if (taskTop != null) {
- taskTop.updateOptionsLocked(topOptions);
- } else {
- topOptions.abort();
- }
+ taskTop.updateOptionsLocked(topOptions);
}
return taskTop;
@@ -4697,7 +4255,7 @@
// The task might have already been running and its visibility needs to be synchronized with
// the visibility of the stack / windows.
- ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
+ ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
mRootActivityContainer.resumeFocusedStacksTopActivities();
}
@@ -5219,7 +4777,7 @@
displayContent.layoutAndAssignWindowLayersIfNeeded();
}
- private void positionChildAtBottom(Task child) {
+ void positionChildAtBottom(Task child) {
// If there are other focusable stacks on the display, the z-order of the display should not
// be changed just because a task was placed at the bottom. E.g. if it is moving the topmost
// task to bottom, the next focusable stack on the same display should be focused.
diff --git a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
index 6ea80d2..304f230 100644
--- a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
@@ -975,7 +975,7 @@
}
}
- void startSpecificActivityLocked(ActivityRecord r, boolean andResume, boolean checkConfig) {
+ void startSpecificActivity(ActivityRecord r, boolean andResume, boolean checkConfig) {
// Is this activity's application already running?
final WindowProcessController wpc =
mService.getProcessController(r.processName, r.info.applicationInfo.uid);
@@ -1742,12 +1742,12 @@
* to the fullscreen stack. This is to guarantee that when we are removing a stack,
* that the client receives onStop() before it is reparented. We do this by detaching
* the stack from the display so that it will be considered invisible when
- * ensureActivitiesVisibleLocked() is called, and all of its activitys will be marked
+ * ensureActivitiesVisible() is called, and all of its activitys will be marked
* invisible as well and added to the stopping list. After which we process the
* stopping list by handling the idle.
*/
stack.mForceHidden = true;
- stack.ensureActivitiesVisibleLocked(null, 0, PRESERVE_WINDOWS);
+ stack.ensureActivitiesVisible(null, 0, PRESERVE_WINDOWS);
stack.mForceHidden = false;
activityIdleInternalLocked(null, false /* fromTimeout */,
true /* processPausingActivites */, null /* configuration */);
@@ -2072,7 +2072,7 @@
mRecentTasks.add(task);
mService.getTaskChangeNotificationController().notifyTaskStackChanged();
- stack.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
+ stack.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
// When launching tasks behind, update the last active time of the top task after the new
// task has been shown briefly
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index be7f887..8455c6d 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -1574,7 +1574,7 @@
// Also, we don't want to resume activities in a task that currently has an overlay
// as the starting activity just needs to be in the visible paused state until the
// over is removed.
- mTargetStack.ensureActivitiesVisibleLocked(mStartActivity, 0, !PRESERVE_WINDOWS);
+ mTargetStack.ensureActivitiesVisible(mStartActivity, 0, !PRESERVE_WINDOWS);
// Go ahead and tell window manager to execute app transition for this activity
// since the app transition will not be triggered through the resume channel.
mTargetStack.getDisplay().mDisplayContent.executeAppTransition();
@@ -1812,7 +1812,7 @@
final boolean resetTask =
reusedActivity != null && (mLaunchFlags & FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0;
if (resetTask) {
- targetTaskTop = mTargetStack.resetTaskIfNeededLocked(targetTaskTop, mStartActivity);
+ targetTaskTop = mTargetStack.resetTaskIfNeeded(targetTaskTop, mStartActivity);
}
if ((mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
diff --git a/services/core/java/com/android/server/wm/AppTransitionController.java b/services/core/java/com/android/server/wm/AppTransitionController.java
index bef6af3..ff1b423 100644
--- a/services/core/java/com/android/server/wm/AppTransitionController.java
+++ b/services/core/java/com/android/server/wm/AppTransitionController.java
@@ -688,15 +688,16 @@
* compare z-order.
*
* @param apps The list of apps to search.
- * @param ignoreHidden If set to true, ignores apps that are {@link ActivityRecord#isHidden}.
+ * @param ignoreInvisible If set to true, ignores apps that are not
+ * {@link ActivityRecord#isVisible}.
* @return The top {@link ActivityRecord}.
*/
- private ActivityRecord getTopApp(ArraySet<ActivityRecord> apps, boolean ignoreHidden) {
+ private ActivityRecord getTopApp(ArraySet<ActivityRecord> apps, boolean ignoreInvisible) {
int topPrefixOrderIndex = Integer.MIN_VALUE;
ActivityRecord topApp = null;
for (int i = apps.size() - 1; i >= 0; i--) {
final ActivityRecord app = apps.valueAt(i);
- if (ignoreHidden && app.isHidden()) {
+ if (ignoreInvisible && !app.isVisible()) {
continue;
}
final int prefixOrderIndex = app.getPrefixOrderIndex();
diff --git a/services/core/java/com/android/server/wm/BlackFrame.java b/services/core/java/com/android/server/wm/BlackFrame.java
index b4cecff..8ab1795 100644
--- a/services/core/java/com/android/server/wm/BlackFrame.java
+++ b/services/core/java/com/android/server/wm/BlackFrame.java
@@ -52,7 +52,6 @@
.setParent(surfaceControl)
.build();
transaction.setWindowCrop(surface, w, h);
- transaction.setLayerStack(surface, dc.getDisplayId());
transaction.setAlpha(surface, 1);
transaction.setLayer(surface, layer);
transaction.setPosition(surface, left, top);
diff --git a/services/core/java/com/android/server/wm/CompatModePackages.java b/services/core/java/com/android/server/wm/CompatModePackages.java
index 104805f..320ca65 100644
--- a/services/core/java/com/android/server/wm/CompatModePackages.java
+++ b/services/core/java/com/android/server/wm/CompatModePackages.java
@@ -346,7 +346,7 @@
false /* preserveWindow */);
// And we need to make sure at this point that all other activities
// are made visible with the correct configuration.
- stack.ensureActivitiesVisibleLocked(starting, 0, !PRESERVE_WINDOWS);
+ stack.ensureActivitiesVisible(starting, 0, !PRESERVE_WINDOWS);
}
}
}
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 456f650..283b92c 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -644,11 +644,11 @@
+ " config reported=" + w.isLastConfigReportedToClient());
final ActivityRecord activity = w.mActivityRecord;
if (gone) Slog.v(TAG, " GONE: mViewVisibility=" + w.mViewVisibility
- + " mRelayoutCalled=" + w.mRelayoutCalled + " hidden=" + w.mToken.isHidden()
+ + " mRelayoutCalled=" + w.mRelayoutCalled + " visible=" + w.mToken.isVisible()
+ " visibleRequested=" + (activity != null && activity.mVisibleRequested)
+ " parentHidden=" + w.isParentWindowHidden());
else Slog.v(TAG, " VIS: mViewVisibility=" + w.mViewVisibility
- + " mRelayoutCalled=" + w.mRelayoutCalled + " hidden=" + w.mToken.isHidden()
+ + " mRelayoutCalled=" + w.mRelayoutCalled + " visible=" + w.mToken.isVisible()
+ " visibleRequested=" + (activity != null && activity.mVisibleRequested)
+ " parentHidden=" + w.isParentWindowHidden());
}
@@ -3053,7 +3053,7 @@
wsa.destroySurface();
mWmService.mForceRemoves.add(w);
mTmpWindow = w;
- } else if (w.mActivityRecord != null && w.mActivityRecord.isClientHidden()) {
+ } else if (w.mActivityRecord != null && !w.mActivityRecord.isClientVisible()) {
Slog.w(TAG_WM, "LEAKED SURFACE (app token hidden): "
+ w + " surface=" + wsa.mSurfaceController
+ " token=" + w.mActivityRecord);
@@ -4512,6 +4512,12 @@
mName = name;
}
+ @Override
+ boolean hasActivity() {
+ // I am a non-app-window-container :P
+ return false;
+ }
+
void addChild(WindowToken token) {
addChild(token, mWindowComparator);
}
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index 8d5f90d..77e557b 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -3126,12 +3126,13 @@
: new AppearanceRegion[]{
new AppearanceRegion(fullscreenAppearance, fullscreenStackBounds)};
final boolean isNavbarColorManagedByIme = result.second;
+ String cause = win.toString();
mHandler.post(() -> {
StatusBarManagerInternal statusBar = getStatusBarManagerInternal();
if (statusBar != null) {
final int displayId = getDisplayId();
statusBar.setDisableFlags(displayId, visibility & StatusBarManager.DISABLE_MASK,
- win.toString());
+ cause);
if (transientState.first.length > 0) {
statusBar.showTransient(displayId, transientState.first);
}
@@ -3143,8 +3144,10 @@
statusBar.topAppWindowChanged(displayId, isFullscreen, isImmersive);
// TODO(b/118118435): Remove this after removing system UI visibilities.
- mDisplayContent.statusBarVisibilityChanged(
- visibility & ~(View.STATUS_BAR_UNHIDE | View.NAVIGATION_BAR_UNHIDE));
+ synchronized (mLock) {
+ mDisplayContent.statusBarVisibilityChanged(
+ visibility & ~(View.STATUS_BAR_UNHIDE | View.NAVIGATION_BAR_UNHIDE));
+ }
}
});
return diff;
diff --git a/services/core/java/com/android/server/wm/DisplayWindowListenerController.java b/services/core/java/com/android/server/wm/DisplayWindowListenerController.java
index dbc452f..2da76ea 100644
--- a/services/core/java/com/android/server/wm/DisplayWindowListenerController.java
+++ b/services/core/java/com/android/server/wm/DisplayWindowListenerController.java
@@ -16,6 +16,7 @@
package com.android.server.wm;
+import android.content.res.Configuration;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.view.IDisplayWindowListener;
@@ -62,6 +63,28 @@
mDisplayListeners.finishBroadcast();
}
+ void dispatchDisplayChanged(ActivityDisplay display, Configuration newConfig) {
+ // Only report changed if this has actually been added to the hierarchy already.
+ boolean isInHierarchy = false;
+ for (int i = 0; i < display.getParent().getChildCount(); ++i) {
+ if (display.getParent().getChildAt(i) == display) {
+ isInHierarchy = true;
+ }
+ }
+ if (!isInHierarchy) {
+ return;
+ }
+ int count = mDisplayListeners.beginBroadcast();
+ for (int i = 0; i < count; ++i) {
+ try {
+ mDisplayListeners.getBroadcastItem(i).onDisplayConfigurationChanged(
+ display.mDisplayId, newConfig);
+ } catch (RemoteException e) {
+ }
+ }
+ mDisplayListeners.finishBroadcast();
+ }
+
void dispatchDisplayRemoved(ActivityDisplay display) {
int count = mDisplayListeners.beginBroadcast();
for (int i = 0; i < count; ++i) {
diff --git a/services/core/java/com/android/server/wm/EnsureActivitiesVisibleHelper.java b/services/core/java/com/android/server/wm/EnsureActivitiesVisibleHelper.java
new file mode 100644
index 0000000..3aae1b1
--- /dev/null
+++ b/services/core/java/com/android/server/wm/EnsureActivitiesVisibleHelper.java
@@ -0,0 +1,196 @@
+/*
+ * 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.wm;
+
+import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
+
+import static com.android.server.wm.ActivityStack.TAG_VISIBILITY;
+import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_VISIBILITY;
+
+import android.util.Slog;
+
+import com.android.internal.util.function.pooled.PooledConsumer;
+import com.android.internal.util.function.pooled.PooledLambda;
+
+/** Helper class to ensure activities are in the right visible state for a container. */
+class EnsureActivitiesVisibleHelper {
+ private final ActivityStack mContiner;
+ private ActivityRecord mTop;
+ private ActivityRecord mStarting;
+ private boolean mAboveTop;
+ private boolean mContainerShouldBeVisible;
+ private boolean mBehindFullscreenActivity;
+ private int mConfigChanges;
+ private boolean mPreserveWindows;
+ private boolean mNotifyClients;
+
+ EnsureActivitiesVisibleHelper(ActivityStack container) {
+ mContiner = container;
+ }
+
+ void reset(ActivityRecord starting, int configChanges, boolean preserveWindows,
+ boolean notifyClients) {
+ mStarting = starting;
+ mTop = mContiner.topRunningActivityLocked();
+ // If the top activity is not fullscreen, then we need to make sure any activities under it
+ // are now visible.
+ mAboveTop = mTop != null;
+ mContainerShouldBeVisible = mContiner.shouldBeVisible(mStarting);
+ mBehindFullscreenActivity = !mContainerShouldBeVisible;
+ mConfigChanges = configChanges;
+ mPreserveWindows = preserveWindows;
+ mNotifyClients = notifyClients;
+ }
+
+ /**
+ * Ensure visibility with an option to also update the configuration of visible activities.
+ * @see ActivityStack#ensureActivitiesVisible(ActivityRecord, int, boolean)
+ * @see RootActivityContainer#ensureActivitiesVisible(ActivityRecord, int, boolean)
+ */
+ void process(ActivityRecord starting, int configChanges, boolean preserveWindows,
+ boolean notifyClients) {
+ reset(starting, configChanges, preserveWindows, notifyClients);
+
+ if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "ensureActivitiesVisible behind " + mTop
+ + " configChanges=0x" + Integer.toHexString(configChanges));
+ if (mTop != null) {
+ mContiner.checkTranslucentActivityWaiting(mTop);
+ }
+
+ // We should not resume activities that being launched behind because these
+ // activities are actually behind other fullscreen activities, but still required
+ // to be visible (such as performing Recents animation).
+ final boolean resumeTopActivity = mTop != null && !mTop.mLaunchTaskBehind
+ && mContiner.isFocusable() && mContiner.isInStackLocked(starting) == null;
+
+ final PooledConsumer f = PooledLambda.obtainConsumer(
+ EnsureActivitiesVisibleHelper::setActivityVisibilityState, this,
+ PooledLambda.__(ActivityRecord.class), resumeTopActivity);
+ mContiner.forAllActivities(f);
+ f.recycle();
+ }
+
+ private void setActivityVisibilityState(ActivityRecord r, final boolean resumeTopActivity) {
+ final boolean isTop = r == mTop;
+ if (mAboveTop && !isTop) {
+ return;
+ }
+ mAboveTop = false;
+
+ final boolean reallyVisible = r.shouldBeVisible(
+ mBehindFullscreenActivity, false /* ignoringKeyguard */);
+
+ // Check whether activity should be visible without Keyguard influence
+ if (r.visibleIgnoringKeyguard) {
+ if (r.occludesParent()) {
+ // At this point, nothing else needs to be shown in this task.
+ if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Fullscreen: at " + r
+ + " stackVisible=" + mContainerShouldBeVisible
+ + " behindFullscreen=" + mBehindFullscreenActivity);
+ mBehindFullscreenActivity = true;
+ } else {
+ mBehindFullscreenActivity = false;
+ }
+ }
+
+ if (reallyVisible) {
+ if (r.finishing) {
+ return;
+ }
+ if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Make visible? " + r
+ + " finishing=" + r.finishing + " state=" + r.getState());
+ // First: if this is not the current activity being started, make
+ // sure it matches the current configuration.
+ if (r != mStarting && mNotifyClients) {
+ r.ensureActivityConfiguration(0 /* globalChanges */, mPreserveWindows,
+ true /* ignoreVisibility */);
+ }
+
+ if (!r.attachedToProcess()) {
+ makeVisibleAndRestartIfNeeded(mStarting, mConfigChanges, isTop,
+ resumeTopActivity && isTop, r);
+ } else if (r.mVisibleRequested) {
+ // If this activity is already visible, then there is nothing to do here.
+ if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY,
+ "Skipping: already visible at " + r);
+
+ if (r.mClientVisibilityDeferred && mNotifyClients) {
+ r.makeClientVisible();
+ }
+
+ r.handleAlreadyVisible();
+ if (mNotifyClients) {
+ r.makeActiveIfNeeded(mStarting);
+ }
+ } else {
+ r.makeVisibleIfNeeded(mStarting, mNotifyClients);
+ }
+ // Aggregate current change flags.
+ mConfigChanges |= r.configChangeFlags;
+ } else {
+ if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Make invisible? " + r
+ + " finishing=" + r.finishing + " state=" + r.getState()
+ + " stackShouldBeVisible=" + mContainerShouldBeVisible
+ + " behindFullscreenActivity=" + mBehindFullscreenActivity
+ + " mLaunchTaskBehind=" + r.mLaunchTaskBehind);
+ r.makeInvisible();
+ }
+
+ final int windowingMode = mContiner.getWindowingMode();
+ if (windowingMode == WINDOWING_MODE_FREEFORM) {
+ // The visibility of tasks and the activities they contain in freeform stack are
+ // determined individually unlike other stacks where the visibility or fullscreen
+ // status of an activity in a previous task affects other.
+ mBehindFullscreenActivity = !mContainerShouldBeVisible;
+ } else if (mContiner.isActivityTypeHome()) {
+ if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Home task: at " + mContiner
+ + " stackShouldBeVisible=" + mContainerShouldBeVisible
+ + " behindFullscreenActivity=" + mBehindFullscreenActivity);
+ // No other task in the home stack should be visible behind the home activity.
+ // Home activities is usually a translucent activity with the wallpaper behind
+ // them. However, when they don't have the wallpaper behind them, we want to
+ // show activities in the next application stack behind them vs. another
+ // task in the home stack like recents.
+ mBehindFullscreenActivity = true;
+ }
+ }
+
+ private void makeVisibleAndRestartIfNeeded(ActivityRecord starting, int configChanges,
+ boolean isTop, boolean andResume, ActivityRecord r) {
+ // We need to make sure the app is running if it's the top, or it is just made visible from
+ // invisible. If the app is already visible, it must have died while it was visible. In this
+ // case, we'll show the dead window but will not restart the app. Otherwise we could end up
+ // thrashing.
+ if (!isTop && r.mVisibleRequested) {
+ return;
+ }
+
+ // This activity needs to be visible, but isn't even running...
+ // get it started and resume if no other stack in this stack is resumed.
+ if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Start and freeze screen for " + r);
+ if (r != starting) {
+ r.startFreezingScreenLocked(configChanges);
+ }
+ if (!r.mVisibleRequested || r.mLaunchTaskBehind) {
+ if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Starting and making visible: " + r);
+ r.setVisibility(true);
+ }
+ if (r != starting) {
+ mContiner.mStackSupervisor.startSpecificActivity(r, andResume, true /* checkConfig */);
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/wm/HighRefreshRateBlacklist.java b/services/core/java/com/android/server/wm/HighRefreshRateBlacklist.java
index 29b6bc4..d9cf637 100644
--- a/services/core/java/com/android/server/wm/HighRefreshRateBlacklist.java
+++ b/services/core/java/com/android/server/wm/HighRefreshRateBlacklist.java
@@ -105,8 +105,10 @@
private class OnPropertiesChangedListener implements DeviceConfig.OnPropertiesChangedListener {
public void onPropertiesChanged(@NonNull DeviceConfig.Properties properties) {
- updateBlacklist(
- properties.getString(KEY_HIGH_REFRESH_RATE_BLACKLIST, null /*default*/));
+ if (properties.getKeyset().contains(KEY_HIGH_REFRESH_RATE_BLACKLIST)) {
+ updateBlacklist(
+ properties.getString(KEY_HIGH_REFRESH_RATE_BLACKLIST, null /*default*/));
+ }
}
}
}
diff --git a/services/core/java/com/android/server/wm/RecentsAnimation.java b/services/core/java/com/android/server/wm/RecentsAnimation.java
index a17bd24..824a3c8 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimation.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimation.java
@@ -134,7 +134,7 @@
if (!targetActivity.attachedToProcess()) {
ProtoLog.d(WM_DEBUG_RECENTS_ANIMATIONS, "Real start recents");
- mStackSupervisor.startSpecificActivityLocked(targetActivity, false /* andResume */,
+ mStackSupervisor.startSpecificActivity(targetActivity, false /* andResume */,
false /* checkConfig */);
// Make sure the activity won't be involved in transition.
if (targetActivity.getDisplayContent() != null) {
@@ -368,7 +368,7 @@
// transition (the target activity will be one of closing apps).
if (!controller.shouldDeferCancelWithScreenshot()
&& !targetStack.isFocusedStackOnDisplay()) {
- targetStack.ensureActivitiesVisibleLocked(null /* starting */,
+ targetStack.ensureActivitiesVisible(null /* starting */,
0 /* starting */, false /* preserveWindows */);
}
// Keep target stack in place, nothing changes, so ignore the transition
diff --git a/services/core/java/com/android/server/wm/ResetTargetTaskHelper.java b/services/core/java/com/android/server/wm/ResetTargetTaskHelper.java
new file mode 100644
index 0000000..413dfd5
--- /dev/null
+++ b/services/core/java/com/android/server/wm/ResetTargetTaskHelper.java
@@ -0,0 +1,295 @@
+/*
+ * 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.wm;
+
+import static com.android.server.wm.ActivityStack.TAG_ADD_REMOVE;
+import static com.android.server.wm.ActivityStack.TAG_TASKS;
+import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_ADD_REMOVE;
+import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_TASKS;
+import static com.android.server.wm.Task.REPARENT_LEAVE_STACK_IN_PLACE;
+
+import android.app.ActivityOptions;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.os.Debug;
+import android.util.Slog;
+
+import com.android.internal.util.function.pooled.PooledConsumer;
+import com.android.internal.util.function.pooled.PooledFunction;
+import com.android.internal.util.function.pooled.PooledLambda;
+
+import java.util.ArrayList;
+
+/** Helper class for processing the reset of a task. */
+class ResetTargetTaskHelper {
+ private Task mTask;
+ private ActivityStack mParent;
+ private Task mTargetTask;
+ private ActivityRecord mRoot;
+ private boolean mForceReset;
+ private boolean mCanMoveOptions;
+ private boolean mTargetTaskFound;
+ private int mActivityReparentPosition;
+ private ActivityOptions mTopOptions;
+ private ArrayList<ActivityRecord> mResultActivities = new ArrayList<>();
+ private ArrayList<ActivityRecord> mAllActivities = new ArrayList<>();
+ private ArrayList<Task> mCreatedTasks = new ArrayList<>();
+
+ private void reset(Task task) {
+ mTask = task;
+ mRoot = null;
+ mCanMoveOptions = true;
+ mTopOptions = null;
+ mResultActivities.clear();
+ mAllActivities.clear();
+ mCreatedTasks.clear();
+ }
+
+ ActivityOptions process(ActivityStack parent, Task targetTask, boolean forceReset) {
+ mParent = parent;
+ mForceReset = forceReset;
+ mTargetTask = targetTask;
+ mTargetTaskFound = false;
+ mActivityReparentPosition = -1;
+
+ final PooledConsumer c = PooledLambda.obtainConsumer(
+ ResetTargetTaskHelper::processTask, this, PooledLambda.__(Task.class));
+ parent.forAllTasks(c);
+ c.recycle();
+
+ reset(null);
+ mParent = null;
+ return mTopOptions;
+ }
+
+ private void processTask(Task task) {
+ reset(task);
+ mRoot = task.getRootActivity(true);
+ if (mRoot == null) return;
+
+ final boolean isTargetTask = task == mTargetTask;
+ if (isTargetTask) mTargetTaskFound = true;
+
+ final PooledFunction f = PooledLambda.obtainFunction(
+ ResetTargetTaskHelper::processActivity, this,
+ PooledLambda.__(ActivityRecord.class), isTargetTask);
+ task.forAllActivities(f);
+ f.recycle();
+
+ processCreatedTasks();
+ }
+
+ private boolean processActivity(ActivityRecord r, boolean isTargetTask) {
+ // End processing if we have reached the root.
+ if (r == mRoot) return true;
+
+ mAllActivities.add(r);
+ final int flags = r.info.flags;
+ final boolean finishOnTaskLaunch =
+ (flags & ActivityInfo.FLAG_FINISH_ON_TASK_LAUNCH) != 0;
+ final boolean allowTaskReparenting =
+ (flags & ActivityInfo.FLAG_ALLOW_TASK_REPARENTING) != 0;
+ final boolean clearWhenTaskReset =
+ (r.intent.getFlags() & Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0;
+
+ if (isTargetTask) {
+ if (!finishOnTaskLaunch && !clearWhenTaskReset) {
+ if (r.resultTo != null) {
+ // If this activity is sending a reply to a previous activity, we can't do
+ // anything with it now until we reach the start of the reply chain.
+ // NOTE: that we are assuming the result is always to the previous activity,
+ // which is almost always the case but we really shouldn't count on.
+ mResultActivities.add(r);
+ return false;
+ }
+ if (allowTaskReparenting && r.taskAffinity != null
+ && !r.taskAffinity.equals(mTask.affinity)) {
+ // If this activity has an affinity for another task, then we need to move
+ // it out of here. We will move it as far out of the way as possible, to the
+ // bottom of the activity stack. This also keeps it correctly ordered with
+ // any activities we previously moved.
+ // TODO: We should probably look for other stacks also, since corresponding
+ // task with the same affinity is unlikely to be in the same stack.
+ final Task targetTask;
+ final ActivityRecord bottom = mParent.getActivity(
+ (ar) -> true, false /*traverseTopToBottom*/);
+
+ if (bottom != null && r.taskAffinity.equals(bottom.getTask().affinity)) {
+ // If the activity currently at the bottom has the same task affinity as
+ // the one we are moving, then merge it into the same task.
+ targetTask = bottom.getTask();
+ if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Start pushing activity "
+ + r + " out to bottom task " + targetTask);
+ } else {
+ targetTask = mParent.createTask(
+ mParent.mStackSupervisor.getNextTaskIdForUserLocked(r.mUserId),
+ r.info, null /* intent */, null /* voiceSession */,
+ null /* voiceInteractor */, false /* toTop */);
+ targetTask.affinityIntent = r.intent;
+ mCreatedTasks.add(targetTask);
+ if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Start pushing activity "
+ + r + " out to new task " + targetTask);
+ }
+
+ mResultActivities.add(r);
+ processResultActivities(r, targetTask, 0 /*bottom*/, true, true);
+ mParent.positionChildAtBottom(targetTask);
+ mParent.mStackSupervisor.mRecentTasks.add(targetTask);
+ return false;
+ }
+ }
+ if (mForceReset || finishOnTaskLaunch || clearWhenTaskReset) {
+ // If the activity should just be removed either because it asks for it, or the
+ // task should be cleared, then finish it and anything that is part of its reply
+ // chain.
+ if (clearWhenTaskReset) {
+ // In this case, we want to finish this activity and everything above it,
+ // so be sneaky and pretend like these are all in the reply chain.
+ finishActivities(mAllActivities, "clearWhenTaskReset");
+ } else {
+ mResultActivities.add(r);
+ finishActivities(mResultActivities, "reset-task");
+ }
+
+ mResultActivities.clear();
+ return false;
+ } else {
+ // If we were in the middle of a chain, well the activity that started it all
+ // doesn't want anything special, so leave it all as-is.
+ mResultActivities.clear();
+ }
+
+ return false;
+
+ } else {
+ mResultActivities.add(r);
+ if (r.resultTo != null) {
+ // If this activity is sending a reply to a previous activity, we can't do
+ // anything with it now until we reach the start of the reply chain.
+ // NOTE: that we are assuming the result is always to the previous activity,
+ // which is almost always the case but we really shouldn't count on.
+ return false;
+ } else if (mTargetTaskFound && allowTaskReparenting && mTargetTask.affinity != null
+ && mTargetTask.affinity.equals(r.taskAffinity)) {
+ // This activity has an affinity for our task. Either remove it if we are
+ // clearing or move it over to our task. Note that we currently punt on the case
+ // where we are resetting a task that is not at the top but who has activities
+ // above with an affinity to it... this is really not a normal case, and we will
+ // need to later pull that task to the front and usually at that point we will
+ // do the reset and pick up those remaining activities. (This only happens if
+ // someone starts an activity in a new task from an activity in a task that is
+ // not currently on top.)
+ if (mForceReset || finishOnTaskLaunch) {
+ finishActivities(mResultActivities, "move-affinity");
+ return false;
+ }
+ if (mActivityReparentPosition == -1) {
+ mActivityReparentPosition = mTargetTask.getChildCount();
+ }
+
+ processResultActivities(
+ r, mTargetTask, mActivityReparentPosition, false, false);
+
+ mParent.positionChildAtTop(mTargetTask);
+
+ // Now we've moved it in to place...but what if this is a singleTop activity and
+ // we have put it on top of another instance of the same activity? Then we drop
+ // the instance below so it remains singleTop.
+ if (r.info.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP) {
+ final ArrayList<ActivityRecord> taskActivities = mTargetTask.mChildren;
+ final int targetNdx = taskActivities.indexOf(r);
+ if (targetNdx > 0) {
+ final ActivityRecord p = taskActivities.get(targetNdx - 1);
+ if (p.intent.getComponent().equals(r.intent.getComponent())) {
+ p.finishIfPossible("replace", false /* oomAdj */);
+ }
+ }
+ }
+ }
+ return false;
+ }
+ }
+
+ private void finishActivities(ArrayList<ActivityRecord> activities, String reason) {
+ boolean noOptions = mCanMoveOptions;
+
+ while (!activities.isEmpty()) {
+ final ActivityRecord p = activities.remove(0);
+ if (p.finishing) continue;
+
+ noOptions = takeOption(p, noOptions);
+
+ if (DEBUG_TASKS) Slog.w(TAG_TASKS,
+ "resetTaskIntendedTask: calling finishActivity on " + p);
+ p.finishIfPossible(reason, false /* oomAdj */);
+ }
+ }
+
+ private void processResultActivities(ActivityRecord target, Task targetTask, int position,
+ boolean ignoreFinishing, boolean takeOptions) {
+ boolean noOptions = mCanMoveOptions;
+
+ while (!mResultActivities.isEmpty()) {
+ final ActivityRecord p = mResultActivities.remove(0);
+ if (ignoreFinishing&& p.finishing) continue;
+
+ if (takeOptions) {
+ noOptions = takeOption(p, noOptions);
+ }
+ if (DEBUG_ADD_REMOVE) Slog.i(TAG_ADD_REMOVE, "Removing activity " + p + " from task="
+ + mTask + " adding to task=" + targetTask + " Callers=" + Debug.getCallers(4));
+ if (DEBUG_TASKS) Slog.v(TAG_TASKS,
+ "Pushing next activity " + p + " out to target's task " + target);
+ p.reparent(targetTask, position, "resetTargetTaskIfNeeded");
+ }
+ }
+
+ private void processCreatedTasks() {
+ if (mCreatedTasks.isEmpty()) return;
+
+ ActivityDisplay display = mParent.getDisplay();
+ final boolean singleTaskInstanceDisplay = display.isSingleTaskInstance();
+ if (singleTaskInstanceDisplay) {
+ display = mParent.mRootActivityContainer.getDefaultDisplay();
+ }
+
+ final int windowingMode = mParent.getWindowingMode();
+ final int activityType = mParent.getActivityType();
+ if (!singleTaskInstanceDisplay && !display.alwaysCreateStack(windowingMode, activityType)) {
+ return;
+ }
+
+ while (!mCreatedTasks.isEmpty()) {
+ final Task targetTask = mCreatedTasks.remove(mCreatedTasks.size() - 1);
+ final ActivityStack targetStack = display.getOrCreateStack(
+ windowingMode, activityType, false /* onTop */);
+ targetTask.reparent(targetStack, false /* toTop */, REPARENT_LEAVE_STACK_IN_PLACE,
+ false /* animate */, true /* deferResume */, "resetTargetTask");
+ }
+ }
+
+ private boolean takeOption(ActivityRecord p, boolean noOptions) {
+ mCanMoveOptions = false;
+ if (noOptions && mTopOptions == null) {
+ mTopOptions = p.takeOptionsLocked(false /* fromClient */);
+ if (mTopOptions != null) {
+ noOptions = false;
+ }
+ }
+ return noOptions;
+ }
+}
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 6ddd943..28c5575 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -1067,12 +1067,30 @@
/** Returns the first non-finishing activity from the bottom. */
ActivityRecord getRootActivity() {
- final int rootActivityIndex = findRootIndex(false /* effectiveRoot */);
- if (rootActivityIndex == -1) {
- // There are no non-finishing activities in the task.
- return null;
+ // TODO: Figure out why we historical ignore relinquish identity for this case...
+ return getRootActivity(true /*ignoreRelinquishIdentity*/, false /*setToBottomIfNone*/);
+ }
+
+ ActivityRecord getRootActivity(boolean setToBottomIfNone) {
+ return getRootActivity(false /*ignoreRelinquishIdentity*/, false /*setToBottomIfNone*/);
+ }
+
+ ActivityRecord getRootActivity(boolean ignoreRelinquishIdentity, boolean setToBottomIfNone) {
+ ActivityRecord root;
+ if (ignoreRelinquishIdentity) {
+ root = getActivity((r) -> !r.finishing, false /*traverseTopToBottom*/);
+ } else {
+ root = getActivity((r) ->
+ !r.finishing && (r.info.flags & FLAG_RELINQUISH_TASK_IDENTITY) == 0,
+ false /*traverseTopToBottom*/);
}
- return getChildAt(rootActivityIndex);
+
+ if (root == null && setToBottomIfNone) {
+ // All activities in the task are either finishing or relinquish task identity.
+ // But we still want to update the intent, so let's use the bottom activity.
+ root = getActivity((r) -> true, false /*traverseTopToBottom*/);
+ }
+ return root;
}
ActivityRecord getTopNonFinishingActivity() {
@@ -2046,17 +2064,22 @@
// could never go away in Honeycomb.
final int compatScreenWidthDp = (int) (mTmpNonDecorBounds.width() / density);
final int compatScreenHeightDp = (int) (mTmpNonDecorBounds.height() / density);
- // We're only overriding LONG, SIZE and COMPAT parts of screenLayout, so we start
- // override calculation with partial default.
// Reducing the screen layout starting from its parent config.
- final int sl = parentConfig.screenLayout
- & (Configuration.SCREENLAYOUT_LONG_MASK | Configuration.SCREENLAYOUT_SIZE_MASK);
- final int longSize = Math.max(compatScreenHeightDp, compatScreenWidthDp);
- final int shortSize = Math.min(compatScreenHeightDp, compatScreenWidthDp);
- inOutConfig.screenLayout = Configuration.reduceScreenLayout(sl, longSize, shortSize);
+ inOutConfig.screenLayout = computeScreenLayoutOverride(parentConfig.screenLayout,
+ compatScreenWidthDp, compatScreenHeightDp);
}
}
+ /** Computes LONG, SIZE and COMPAT parts of {@link Configuration#screenLayout}. */
+ static int computeScreenLayoutOverride(int sourceScreenLayout, int screenWidthDp,
+ int screenHeightDp) {
+ sourceScreenLayout = sourceScreenLayout
+ & (Configuration.SCREENLAYOUT_LONG_MASK | Configuration.SCREENLAYOUT_SIZE_MASK);
+ final int longSize = Math.max(screenWidthDp, screenHeightDp);
+ final int shortSize = Math.min(screenWidthDp, screenHeightDp);
+ return Configuration.reduceScreenLayout(sourceScreenLayout, longSize, shortSize);
+ }
+
@Override
void resolveOverrideConfiguration(Configuration newParentConfig) {
mTmpBounds.set(getResolvedOverrideConfiguration().windowConfiguration.getBounds());
@@ -2508,7 +2531,7 @@
for (int i = mChildren.size() - 1; i >= 0; i--) {
final ActivityRecord token = mChildren.get(i);
// skip hidden (or about to hide) apps
- if (token.mIsExiting || token.isClientHidden() || !token.mVisibleRequested) {
+ if (token.mIsExiting || !token.isClientVisible() || !token.mVisibleRequested) {
continue;
}
final WindowState win = token.findMainWindow();
@@ -2726,10 +2749,9 @@
ActivityRecord getTopVisibleActivity() {
for (int i = mChildren.size() - 1; i >= 0; i--) {
- final ActivityRecord token = mChildren.get(i);
- // skip hidden (or about to hide) apps
- if (!token.mIsExiting && !token.isClientHidden() && token.mVisibleRequested) {
- return token;
+ final ActivityRecord activity = mChildren.get(i);
+ if (!activity.mIsExiting && activity.isClientVisible() && activity.mVisibleRequested) {
+ return activity;
}
}
return null;
diff --git a/services/core/java/com/android/server/wm/WallpaperController.java b/services/core/java/com/android/server/wm/WallpaperController.java
index ef79403..6ff4b2e 100644
--- a/services/core/java/com/android/server/wm/WallpaperController.java
+++ b/services/core/java/com/android/server/wm/WallpaperController.java
@@ -120,7 +120,7 @@
}
mFindResults.resetTopWallpaper = true;
- if (w.mActivityRecord != null && w.mActivityRecord.isHidden()
+ if (w.mActivityRecord != null && !w.mActivityRecord.isVisible()
&& !w.mActivityRecord.isAnimating(TRANSITION)) {
// If this window's app token is hidden and not animating, it is of no interest to us.
@@ -278,9 +278,11 @@
for (int i = mWallpaperTokens.size() - 1; i >= 0; i--) {
final WallpaperWindowToken token = mWallpaperTokens.get(i);
token.hideWallpaperToken(wasDeferred, "hideWallpapers");
- if (DEBUG_WALLPAPER_LIGHT && !token.isHidden()) Slog.d(TAG, "Hiding wallpaper " + token
- + " from " + winGoingAway + " target=" + mWallpaperTarget + " prev="
- + mPrevWallpaperTarget + "\n" + Debug.getCallers(5, " "));
+ if (DEBUG_WALLPAPER_LIGHT && token.isVisible()) {
+ Slog.d(TAG, "Hiding wallpaper " + token
+ + " from " + winGoingAway + " target=" + mWallpaperTarget + " prev="
+ + mPrevWallpaperTarget + "\n" + Debug.getCallers(5, " "));
+ }
}
}
diff --git a/services/core/java/com/android/server/wm/WallpaperWindowToken.java b/services/core/java/com/android/server/wm/WallpaperWindowToken.java
index 528cece..d23bf97 100644
--- a/services/core/java/com/android/server/wm/WallpaperWindowToken.java
+++ b/services/core/java/com/android/server/wm/WallpaperWindowToken.java
@@ -56,7 +56,6 @@
final WindowState wallpaper = mChildren.get(j);
wallpaper.hideWallpaperWindow(wasDeferred, reason);
}
- setHidden(true);
}
void sendWindowWallpaperCommand(
@@ -88,9 +87,7 @@
final int dw = displayInfo.logicalWidth;
final int dh = displayInfo.logicalHeight;
- if (isHidden() == visible) {
- setHidden(!visible);
-
+ if (isVisible() != visible) {
// Need to do a layout to ensure the wallpaper now has the correct size.
mDisplayContent.setLayoutNeeded();
}
@@ -118,10 +115,9 @@
void updateWallpaperWindows(boolean visible) {
- if (isHidden() == visible) {
+ if (isVisible() != visible) {
if (DEBUG_WALLPAPER_LIGHT) Slog.d(TAG,
- "Wallpaper token " + token + " hidden=" + !visible);
- setHidden(!visible);
+ "Wallpaper token " + token + " visible=" + visible);
// Need to do a layout to ensure the wallpaper now has the correct size.
mDisplayContent.setLayoutNeeded();
}
diff --git a/services/core/java/com/android/server/wm/Watermark.java b/services/core/java/com/android/server/wm/Watermark.java
index 725aaa48..4e1b217 100644
--- a/services/core/java/com/android/server/wm/Watermark.java
+++ b/services/core/java/com/android/server/wm/Watermark.java
@@ -121,8 +121,7 @@
.setBufferSize(1, 1)
.setFormat(PixelFormat.TRANSLUCENT)
.build();
- t.setLayerStack(ctrl, mDisplay.getLayerStack())
- .setLayer(ctrl, WindowManagerService.TYPE_LAYER_MULTIPLIER * 100)
+ t.setLayer(ctrl, WindowManagerService.TYPE_LAYER_MULTIPLIER * 100)
.setPosition(ctrl, 0, 0)
.show(ctrl);
mSurface.copyFrom(ctrl);
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index 3e78d5e..453514b2 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -79,6 +79,7 @@
import java.util.Comparator;
import java.util.LinkedList;
import java.util.function.Consumer;
+import java.util.function.Function;
import java.util.function.Predicate;
/**
@@ -775,10 +776,10 @@
/**
* @return {@code true} if in this subtree of the hierarchy we have an
- * {@ode ActivityRecord#isAnimating(TRANSITION)}, {@code false} otherwise.
+ * {@code ActivityRecord#isAnimating(TRANSITION)}, {@code false} otherwise.
*/
boolean isAppTransitioning() {
- return forAllActivities(app -> app.isAnimating(TRANSITION));
+ return getActivity(app -> app.isAnimating(TRANSITION)) != null;
}
/**
@@ -1094,7 +1095,7 @@
wrapper.release();
}
- boolean forAllActivities(ToBooleanFunction<ActivityRecord> callback) {
+ boolean forAllActivities(Function<ActivityRecord, Boolean> callback) {
for (int i = mChildren.size() - 1; i >= 0; --i) {
if (mChildren.get(i).forAllActivities(callback)) {
return true;
@@ -1103,6 +1104,72 @@
return false;
}
+ void forAllActivities(Consumer<ActivityRecord> callback) {
+ forAllActivities(callback, true /*traverseTopToBottom*/);
+ }
+
+ void forAllActivities(Consumer<ActivityRecord> callback, boolean traverseTopToBottom) {
+ if (traverseTopToBottom) {
+ for (int i = mChildren.size() - 1; i >= 0; --i) {
+ mChildren.get(i).forAllActivities(callback, traverseTopToBottom);
+ }
+ } else {
+ final int count = mChildren.size();
+ for (int i = 0; i < count; i++) {
+ mChildren.get(i).forAllActivities(callback, traverseTopToBottom);
+ }
+ }
+ }
+
+ /** @return {@code true} if this node or any of its children contains an activity. */
+ boolean hasActivity() {
+ for (int i = mChildren.size() - 1; i >= 0; --i) {
+ if (mChildren.get(i).hasActivity()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ ActivityRecord getActivity(Predicate<ActivityRecord> callback) {
+ return getActivity(callback, true /*traverseTopToBottom*/);
+ }
+
+ ActivityRecord getActivity(Predicate<ActivityRecord> callback, boolean traverseTopToBottom) {
+ if (traverseTopToBottom) {
+ for (int i = mChildren.size() - 1; i >= 0; --i) {
+ final ActivityRecord r = mChildren.get(i).getActivity(callback, traverseTopToBottom);
+ if (r != null) {
+ return r;
+ }
+ }
+ } else {
+ final int count = mChildren.size();
+ for (int i = 0; i < count; i++) {
+ final ActivityRecord r = mChildren.get(i).getActivity(callback, traverseTopToBottom);
+ if (r != null) {
+ return r;
+ }
+ }
+ }
+
+ return null;
+ }
+
+ ActivityRecord getTopActivity(boolean includeFinishing, boolean includeOverlays) {
+ // Break down into 4 calls to avoid object creation due to capturing input params.
+ if (includeFinishing) {
+ if (includeOverlays) {
+ return getActivity((r) -> true);
+ }
+ return getActivity((r) -> !r.mTaskOverlay);
+ } else if (includeOverlays) {
+ return getActivity((r) -> !r.finishing);
+ }
+
+ return getActivity((r) -> !r.finishing && !r.mTaskOverlay);
+ }
+
void forAllWallpaperWindows(Consumer<WallpaperWindowToken> callback) {
for (int i = mChildren.size() - 1; i >= 0; --i) {
mChildren.get(i).forAllWallpaperWindows(callback);
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index a42f2e1..a2467e6 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -1668,7 +1668,7 @@
if (mInTouchMode) {
res |= WindowManagerGlobal.ADD_FLAG_IN_TOUCH_MODE;
}
- if (win.mActivityRecord == null || !win.mActivityRecord.isClientHidden()) {
+ if (win.mActivityRecord == null || win.mActivityRecord.isClientVisible()) {
res |= WindowManagerGlobal.ADD_FLAG_APP_VISIBLE;
}
@@ -2201,7 +2201,7 @@
// associated appToken is not hidden.
final boolean shouldRelayout = viewVisibility == View.VISIBLE &&
(win.mActivityRecord == null || win.mAttrs.type == TYPE_APPLICATION_STARTING
- || !win.mActivityRecord.isClientHidden());
+ || win.mActivityRecord.isClientVisible());
// If we are not currently running the exit animation, we need to see about starting
// one.
diff --git a/services/core/java/com/android/server/wm/WindowManagerShellCommand.java b/services/core/java/com/android/server/wm/WindowManagerShellCommand.java
index 2218366..5da3eb6 100644
--- a/services/core/java/com/android/server/wm/WindowManagerShellCommand.java
+++ b/services/core/java/com/android/server/wm/WindowManagerShellCommand.java
@@ -20,7 +20,6 @@
import android.graphics.Point;
import android.graphics.Rect;
-import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.os.ShellCommand;
import android.os.UserHandle;
@@ -352,9 +351,7 @@
}
private int runDumpVisibleWindowViews(PrintWriter pw) {
- ParcelFileDescriptor outFile = openFileForSystem(getNextArgRequired(), "w");
- try (ZipOutputStream out = new ZipOutputStream(
- new ParcelFileDescriptor.AutoCloseOutputStream(outFile))) {
+ try (ZipOutputStream out = new ZipOutputStream(getRawOutputStream())) {
ArrayList<Pair<String, ByteTransferPipe>> requestList = new ArrayList<>();
synchronized (mInternal.mGlobalLock) {
// Request dump from all windows parallelly before writing to disk.
@@ -368,7 +365,6 @@
requestList.add(Pair.create(w.getName(), pipe));
} catch (IOException | RemoteException e) {
// Skip this window
- pw.println("Error for window " + w.getName() + " : " + e.getMessage());
if (pipe != null) {
pipe.kill();
}
@@ -382,8 +378,6 @@
data = entry.second.get();
} catch (IOException e) {
// Ignore this window
- pw.println(
- "Error for window " + entry.first + " : " + e.getMessage());
continue;
}
out.putNextEntry(new ZipEntry(entry.first));
@@ -414,7 +408,7 @@
pw.println(" Dismiss the keyguard, prompting user for auth if necessary.");
pw.println(" set-user-rotation [free|lock] [-d DISPLAY_ID] [rotation]");
pw.println(" Set user rotation mode and user rotation.");
- pw.println(" dump-visible-window-views out-file");
+ pw.println(" dump-visible-window-views");
pw.println(" Dumps the encoded view hierarchies of visible windows");
pw.println(" set-fix-to-user-rotation [-d DISPLAY_ID] [enabled|disabled]");
pw.println(" Enable or disable rotating display for app requested orientation.");
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 593b84f..0441669 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -1569,7 +1569,7 @@
* not the pending requested hidden state.
*/
boolean isVisibleNow() {
- return (!mToken.isHidden() || mAttrs.type == TYPE_APPLICATION_STARTING)
+ return (mToken.isVisible() || mAttrs.type == TYPE_APPLICATION_STARTING)
&& isVisible();
}
@@ -1642,7 +1642,7 @@
return false;
}
final boolean parentAndClientVisible = !isParentWindowHidden()
- && mViewVisibility == View.VISIBLE && !mToken.isHidden();
+ && mViewVisibility == View.VISIBLE && mToken.isVisible();
return mHasSurface && isVisibleByPolicy() && !mDestroying
&& (parentAndClientVisible || isAnimating(TRANSITION | PARENTS));
}
@@ -1661,7 +1661,7 @@
} else {
final Task task = getTask();
final boolean canFromTask = task != null && task.canAffectSystemUiFlags();
- return canFromTask && !mActivityRecord.isHidden();
+ return canFromTask && mActivityRecord.isVisible();
}
}
@@ -1690,7 +1690,7 @@
final ActivityRecord atoken = mActivityRecord;
return mViewVisibility == View.GONE
|| !mRelayoutCalled
- || (atoken == null && mToken.isHidden())
+ || (atoken == null && !mToken.isVisible())
|| (atoken != null && !atoken.mVisibleRequested)
|| isParentWindowGoneForLayout()
|| (mAnimatingExit && !isAnimatingLw())
@@ -2595,7 +2595,7 @@
* interacts with it.
*/
private boolean shouldKeepVisibleDeadAppWindow() {
- if (!isWinVisibleLw() || mActivityRecord == null || mActivityRecord.isClientHidden()) {
+ if (!isWinVisibleLw() || mActivityRecord == null || !mActivityRecord.isClientVisible()) {
// Not a visible app window or the app isn't dead.
return false;
}
@@ -2907,13 +2907,13 @@
void sendAppVisibilityToClients() {
super.sendAppVisibilityToClients();
- final boolean clientHidden = mActivityRecord.isClientHidden();
- if (mAttrs.type == TYPE_APPLICATION_STARTING && clientHidden) {
+ final boolean clientVisible = mActivityRecord.isClientVisible();
+ if (mAttrs.type == TYPE_APPLICATION_STARTING && !clientVisible) {
// Don't hide the starting window.
return;
}
- if (clientHidden) {
+ if (!clientVisible) {
// Once we are notifying the client that it's visibility has changed, we need to prevent
// it from destroying child surfaces until the animation has finished. We do this by
// detaching any surface control the client added from the client.
@@ -2927,8 +2927,8 @@
try {
if (DEBUG_VISIBILITY) Slog.v(TAG,
- "Setting visibility of " + this + ": " + (!clientHidden));
- mClient.dispatchAppVisibility(!clientHidden);
+ "Setting visibility of " + this + ": " + clientVisible);
+ mClient.dispatchAppVisibility(clientVisible);
} catch (RemoteException e) {
}
}
@@ -4170,7 +4170,7 @@
+ " parentHidden=" + isParentWindowHidden()
+ " tok.visibleRequested="
+ (mActivityRecord != null && mActivityRecord.mVisibleRequested)
- + " tok.hidden=" + (mActivityRecord != null && mActivityRecord.isHidden())
+ + " tok.visible=" + (mActivityRecord != null && mActivityRecord.isVisible())
+ " animating=" + isAnimating(TRANSITION | PARENTS)
+ " tok animating="
+ (mActivityRecord != null && mActivityRecord.isAnimating(TRANSITION))
diff --git a/services/core/java/com/android/server/wm/WindowToken.java b/services/core/java/com/android/server/wm/WindowToken.java
index 057f493..287d7cd 100644
--- a/services/core/java/com/android/server/wm/WindowToken.java
+++ b/services/core/java/com/android/server/wm/WindowToken.java
@@ -29,7 +29,6 @@
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL;
import static com.android.server.wm.WindowTokenProto.HASH_CODE;
-import static com.android.server.wm.WindowTokenProto.HIDDEN;
import static com.android.server.wm.WindowTokenProto.PAUSED;
import static com.android.server.wm.WindowTokenProto.WAITING_TO_SHOW;
import static com.android.server.wm.WindowTokenProto.WINDOWS;
@@ -72,9 +71,6 @@
// Is key dispatching paused for this token?
boolean paused = false;
- // Should this token's windows be hidden?
- private boolean mHidden;
-
// Temporary for finding which tokens no longer have visible windows.
boolean hasVisible;
@@ -124,16 +120,6 @@
}
}
- void setHidden(boolean hidden) {
- if (hidden != mHidden) {
- mHidden = hidden;
- }
- }
-
- boolean isHidden() {
- return mHidden;
- }
-
void removeAllWindowsIfPossible() {
for (int i = mChildren.size() - 1; i >= 0; --i) {
final WindowState win = mChildren.get(i);
@@ -152,7 +138,7 @@
// This token is exiting, so allow it to be removed when it no longer contains any windows.
mPersistOnEmpty = false;
- if (mHidden) {
+ if (!isVisible()) {
return;
}
@@ -165,7 +151,10 @@
changed |= win.onSetAppExiting();
}
- setHidden(true);
+ final ActivityRecord app = asActivityRecord();
+ if (app != null) {
+ app.setVisible(false);
+ }
if (changed) {
mWmService.mWindowPlacerLocked.performSurfacePlacement();
@@ -282,7 +271,6 @@
final WindowState w = mChildren.get(i);
w.writeToProto(proto, WINDOWS, logLevel);
}
- proto.write(HIDDEN, mHidden);
proto.write(WAITING_TO_SHOW, waitingToShow);
proto.write(PAUSED, paused);
proto.end(token);
@@ -292,7 +280,6 @@
super.dump(pw, prefix, dumpAll);
pw.print(prefix); pw.print("windows="); pw.println(mChildren);
pw.print(prefix); pw.print("windowType="); pw.print(windowType);
- pw.print(" hidden="); pw.print(mHidden);
pw.print(" hasVisible="); pw.println(hasVisible);
if (waitingToShow) {
pw.print(prefix); pw.print("waitingToShow="); pw.print(waitingToShow);
diff --git a/services/core/jni/com_android_server_VibratorService.cpp b/services/core/jni/com_android_server_VibratorService.cpp
index 746610d..612a1e7 100644
--- a/services/core/jni/com_android_server_VibratorService.cpp
+++ b/services/core/jni/com_android_server_VibratorService.cpp
@@ -291,7 +291,7 @@
static void vibratorSetAmplitude(JNIEnv*, jclass, jint amplitude) {
if (auto hal = getHal<aidl::IVibrator>()) {
- auto status = hal->call(&aidl::IVibrator::IVibrator::setAmplitude, amplitude);
+ auto status = hal->call(&aidl::IVibrator::IVibrator::setAmplitude, static_cast<float>(amplitude) / UINT8_MAX);
if (!status.isOk()) {
ALOGE("Failed to set vibrator amplitude: %s", status.toString8().string());
}
diff --git a/services/coverage/Android.bp b/services/coverage/Android.bp
index 16c9c1b..e4f5464 100644
--- a/services/coverage/Android.bp
+++ b/services/coverage/Android.bp
@@ -1,5 +1,12 @@
+filegroup {
+ name: "services.coverage-sources",
+ srcs: ["java/**/*.java"],
+ path: "java",
+ visibility: ["//frameworks/base/services"],
+}
+
java_library_static {
name: "services.coverage",
- srcs: ["java/**/*.java"],
+ srcs: [":services.coverage-sources"],
libs: ["jacocoagent"],
}
diff --git a/services/devicepolicy/Android.bp b/services/devicepolicy/Android.bp
index bffa44e..380ee94 100644
--- a/services/devicepolicy/Android.bp
+++ b/services/devicepolicy/Android.bp
@@ -1,6 +1,13 @@
+filegroup {
+ name: "services.devicepolicy-sources",
+ srcs: ["java/**/*.java"],
+ path: "java",
+ visibility: ["//frameworks/base/services"],
+}
+
java_library_static {
name: "services.devicepolicy",
- srcs: ["java/**/*.java"],
+ srcs: [":services.devicepolicy-sources"],
libs: [
"services.core",
@@ -15,4 +22,4 @@
platform_compat_config {
name: "services-devicepolicy-platform-compat-config",
src: ":services.devicepolicy",
-}
\ No newline at end of file
+}
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index f1ed1d9..39d840f 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -281,7 +281,8 @@
"com.android.server.DeviceIdleController";
private static final String BLOB_STORE_MANAGER_SERVICE_CLASS =
"com.android.server.blob.BlobStoreManagerService";
-
+ private static final String APP_SEARCH_MANAGER_SERVICE_CLASS =
+ "com.android.server.appsearch.AppSearchManagerService";
private static final String PERSISTENT_DATA_BLOCK_PROP = "ro.frp.pst";
private static final String UNCRYPT_PACKAGE_FILE = "/cache/recovery/uncrypt_file";
@@ -704,7 +705,7 @@
// Bring up recovery system in case a rescue party needs a reboot
t.traceBegin("StartRecoverySystemService");
- mSystemServiceManager.startService(RecoverySystemService.class);
+ mSystemServiceManager.startService(RecoverySystemService.Lifecycle.class);
t.traceEnd();
// Now that we have the bare essentials of the OS up and running, take
@@ -2023,6 +2024,10 @@
mSystemServiceManager.startBootPhase(t, SystemService.PHASE_DEVICE_SPECIFIC_SERVICES_READY);
t.traceEnd();
+ t.traceBegin("AppSearchManagerService");
+ mSystemServiceManager.startService(APP_SEARCH_MANAGER_SERVICE_CLASS);
+ t.traceEnd();
+
// These are needed to propagate to the runnable below.
final NetworkManagementService networkManagementF = networkManagement;
final NetworkStatsService networkStatsF = networkStats;
diff --git a/services/midi/Android.bp b/services/midi/Android.bp
index 3745e89..20e0083 100644
--- a/services/midi/Android.bp
+++ b/services/midi/Android.bp
@@ -1,5 +1,12 @@
+filegroup {
+ name: "services.midi-sources",
+ srcs: ["java/**/*.java"],
+ path: "java",
+ visibility: ["//frameworks/base/services"],
+}
+
java_library_static {
name: "services.midi",
- srcs: ["java/**/*.java"],
+ srcs: [":services.midi-sources"],
libs: ["services.core"],
}
diff --git a/services/net/Android.bp b/services/net/Android.bp
index c56ecd6..7ef9f44 100644
--- a/services/net/Android.bp
+++ b/services/net/Android.bp
@@ -1,38 +1,34 @@
+filegroup {
+ name: "services.net-sources",
+ srcs: ["java/**/*.java"],
+ path: "java",
+ visibility: ["//frameworks/base/services"],
+}
+
java_library_static {
name: "services.net",
srcs: [
+ ":net-module-utils-srcs",
":tethering-servicesnet-srcs",
- "java/**/*.java",
+ ":services.net-sources",
],
static_libs: [
"dnsresolver_aidl_interface-V2-java",
"netd_aidl_interface-unstable-java",
+ "netlink-client",
"networkstack-client",
"tethering-client",
],
}
filegroup {
- name: "services-networkstack-shared-srcs",
- srcs: [
- "java/android/net/ip/InterfaceController.java", // TODO: move to NetworkStack with tethering
- "java/android/net/util/InterfaceParams.java", // TODO: move to NetworkStack with IpServer
- "java/android/net/shared/*.java",
- "java/android/net/netlink/*.java",
- ],
-}
-
-filegroup {
name: "services-tethering-shared-srcs",
srcs: [
":framework-annotations",
"java/android/net/ConnectivityModuleConnector.java",
"java/android/net/NetworkStackClient.java",
- "java/android/net/ip/InterfaceController.java",
- "java/android/net/netlink/*.java",
- "java/android/net/util/InterfaceParams.java",
"java/android/net/util/NetdService.java",
"java/android/net/util/NetworkConstants.java",
- "java/android/net/util/SharedLog.java"
],
+ visibility: ["//frameworks/base/packages/Tethering"],
}
diff --git a/services/net/java/android/net/ip/InterfaceController.java b/services/net/java/android/net/ip/InterfaceController.java
deleted file mode 100644
index 970bc9c..0000000
--- a/services/net/java/android/net/ip/InterfaceController.java
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
- * 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.
- */
-
-package android.net.ip;
-
-import android.net.INetd;
-import android.net.InterfaceConfigurationParcel;
-import android.net.LinkAddress;
-import android.net.util.SharedLog;
-import android.os.RemoteException;
-import android.os.ServiceSpecificException;
-import android.system.OsConstants;
-
-import java.net.Inet4Address;
-import java.net.InetAddress;
-
-
-/**
- * Encapsulates the multiple IP configuration operations performed on an interface.
- *
- * TODO: refactor/eliminate the redundant ways to set and clear addresses.
- *
- * @hide
- */
-public class InterfaceController {
- private final static boolean DBG = false;
-
- private final String mIfName;
- private final INetd mNetd;
- private final SharedLog mLog;
-
- public InterfaceController(String ifname, INetd netd, SharedLog log) {
- mIfName = ifname;
- mNetd = netd;
- mLog = log;
- }
-
- private boolean setInterfaceAddress(LinkAddress addr) {
- final InterfaceConfigurationParcel ifConfig = new InterfaceConfigurationParcel();
- ifConfig.ifName = mIfName;
- ifConfig.ipv4Addr = addr.getAddress().getHostAddress();
- ifConfig.prefixLength = addr.getPrefixLength();
- ifConfig.hwAddr = "";
- ifConfig.flags = new String[0];
- try {
- mNetd.interfaceSetCfg(ifConfig);
- } catch (RemoteException | ServiceSpecificException e) {
- logError("Setting IPv4 address to %s/%d failed: %s",
- ifConfig.ipv4Addr, ifConfig.prefixLength, e);
- return false;
- }
- return true;
- }
-
- /**
- * Set the IPv4 address of the interface.
- */
- public boolean setIPv4Address(LinkAddress address) {
- if (!(address.getAddress() instanceof Inet4Address)) {
- return false;
- }
- return setInterfaceAddress(address);
- }
-
- /**
- * Clear the IPv4Address of the interface.
- */
- public boolean clearIPv4Address() {
- return setInterfaceAddress(new LinkAddress("0.0.0.0/0"));
- }
-
- private boolean setEnableIPv6(boolean enabled) {
- try {
- mNetd.interfaceSetEnableIPv6(mIfName, enabled);
- } catch (RemoteException | ServiceSpecificException e) {
- logError("%s IPv6 failed: %s", (enabled ? "enabling" : "disabling"), e);
- return false;
- }
- return true;
- }
-
- /**
- * Enable IPv6 on the interface.
- */
- public boolean enableIPv6() {
- return setEnableIPv6(true);
- }
-
- /**
- * Disable IPv6 on the interface.
- */
- public boolean disableIPv6() {
- return setEnableIPv6(false);
- }
-
- /**
- * Enable or disable IPv6 privacy extensions on the interface.
- * @param enabled Whether the extensions should be enabled.
- */
- public boolean setIPv6PrivacyExtensions(boolean enabled) {
- try {
- mNetd.interfaceSetIPv6PrivacyExtensions(mIfName, enabled);
- } catch (RemoteException | ServiceSpecificException e) {
- logError("error %s IPv6 privacy extensions: %s",
- (enabled ? "enabling" : "disabling"), e);
- return false;
- }
- return true;
- }
-
- /**
- * Set IPv6 address generation mode on the interface.
- *
- * <p>IPv6 should be disabled before changing the mode.
- */
- public boolean setIPv6AddrGenModeIfSupported(int mode) {
- try {
- mNetd.setIPv6AddrGenMode(mIfName, mode);
- } catch (RemoteException e) {
- logError("Unable to set IPv6 addrgen mode: %s", e);
- return false;
- } catch (ServiceSpecificException e) {
- if (e.errorCode != OsConstants.EOPNOTSUPP) {
- logError("Unable to set IPv6 addrgen mode: %s", e);
- return false;
- }
- }
- return true;
- }
-
- /**
- * Add an address to the interface.
- */
- public boolean addAddress(LinkAddress addr) {
- return addAddress(addr.getAddress(), addr.getPrefixLength());
- }
-
- /**
- * Add an address to the interface.
- */
- public boolean addAddress(InetAddress ip, int prefixLen) {
- try {
- mNetd.interfaceAddAddress(mIfName, ip.getHostAddress(), prefixLen);
- } catch (ServiceSpecificException | RemoteException e) {
- logError("failed to add %s/%d: %s", ip, prefixLen, e);
- return false;
- }
- return true;
- }
-
- /**
- * Remove an address from the interface.
- */
- public boolean removeAddress(InetAddress ip, int prefixLen) {
- try {
- mNetd.interfaceDelAddress(mIfName, ip.getHostAddress(), prefixLen);
- } catch (ServiceSpecificException | RemoteException e) {
- logError("failed to remove %s/%d: %s", ip, prefixLen, e);
- return false;
- }
- return true;
- }
-
- /**
- * Remove all addresses from the interface.
- */
- public boolean clearAllAddresses() {
- try {
- mNetd.interfaceClearAddrs(mIfName);
- } catch (Exception e) {
- logError("Failed to clear addresses: %s", e);
- return false;
- }
- return true;
- }
-
- private void logError(String fmt, Object... args) {
- mLog.e(String.format(fmt, args));
- }
-}
diff --git a/services/net/java/android/net/netlink/ConntrackMessage.java b/services/net/java/android/net/netlink/ConntrackMessage.java
deleted file mode 100644
index 6978739..0000000
--- a/services/net/java/android/net/netlink/ConntrackMessage.java
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * 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.
- */
-
-package android.net.netlink;
-
-import static android.net.netlink.StructNlMsgHdr.NLM_F_ACK;
-import static android.net.netlink.StructNlMsgHdr.NLM_F_REPLACE;
-import static android.net.netlink.StructNlMsgHdr.NLM_F_REQUEST;
-
-import static java.nio.ByteOrder.BIG_ENDIAN;
-
-import android.system.OsConstants;
-
-import java.net.Inet4Address;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-
-
-/**
- * A NetlinkMessage subclass for netlink conntrack messages.
- *
- * see also: <linux_src>/include/uapi/linux/netfilter/nfnetlink_conntrack.h
- *
- * @hide
- */
-public class ConntrackMessage extends NetlinkMessage {
- public static final int STRUCT_SIZE = StructNlMsgHdr.STRUCT_SIZE + StructNfGenMsg.STRUCT_SIZE;
-
- public static final short NFNL_SUBSYS_CTNETLINK = 1;
- public static final short IPCTNL_MSG_CT_NEW = 0;
-
- // enum ctattr_type
- public static final short CTA_TUPLE_ORIG = 1;
- public static final short CTA_TUPLE_REPLY = 2;
- public static final short CTA_TIMEOUT = 7;
-
- // enum ctattr_tuple
- public static final short CTA_TUPLE_IP = 1;
- public static final short CTA_TUPLE_PROTO = 2;
-
- // enum ctattr_ip
- public static final short CTA_IP_V4_SRC = 1;
- public static final short CTA_IP_V4_DST = 2;
-
- // enum ctattr_l4proto
- public static final short CTA_PROTO_NUM = 1;
- public static final short CTA_PROTO_SRC_PORT = 2;
- public static final short CTA_PROTO_DST_PORT = 3;
-
- public static byte[] newIPv4TimeoutUpdateRequest(
- int proto, Inet4Address src, int sport, Inet4Address dst, int dport, int timeoutSec) {
- // *** STYLE WARNING ***
- //
- // Code below this point uses extra block indentation to highlight the
- // packing of nested tuple netlink attribute types.
- final StructNlAttr ctaTupleOrig = new StructNlAttr(CTA_TUPLE_ORIG,
- new StructNlAttr(CTA_TUPLE_IP,
- new StructNlAttr(CTA_IP_V4_SRC, src),
- new StructNlAttr(CTA_IP_V4_DST, dst)),
- new StructNlAttr(CTA_TUPLE_PROTO,
- new StructNlAttr(CTA_PROTO_NUM, (byte) proto),
- new StructNlAttr(CTA_PROTO_SRC_PORT, (short) sport, BIG_ENDIAN),
- new StructNlAttr(CTA_PROTO_DST_PORT, (short) dport, BIG_ENDIAN)));
-
- final StructNlAttr ctaTimeout = new StructNlAttr(CTA_TIMEOUT, timeoutSec, BIG_ENDIAN);
-
- final int payloadLength = ctaTupleOrig.getAlignedLength() + ctaTimeout.getAlignedLength();
- final byte[] bytes = new byte[STRUCT_SIZE + payloadLength];
- final ByteBuffer byteBuffer = ByteBuffer.wrap(bytes);
- byteBuffer.order(ByteOrder.nativeOrder());
-
- final ConntrackMessage ctmsg = new ConntrackMessage();
- ctmsg.mHeader.nlmsg_len = bytes.length;
- ctmsg.mHeader.nlmsg_type = (NFNL_SUBSYS_CTNETLINK << 8) | IPCTNL_MSG_CT_NEW;
- ctmsg.mHeader.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_REPLACE;
- ctmsg.mHeader.nlmsg_seq = 1;
- ctmsg.pack(byteBuffer);
-
- ctaTupleOrig.pack(byteBuffer);
- ctaTimeout.pack(byteBuffer);
-
- return bytes;
- }
-
- protected StructNfGenMsg mNfGenMsg;
-
- private ConntrackMessage() {
- super(new StructNlMsgHdr());
- mNfGenMsg = new StructNfGenMsg((byte) OsConstants.AF_INET);
- }
-
- public void pack(ByteBuffer byteBuffer) {
- mHeader.pack(byteBuffer);
- mNfGenMsg.pack(byteBuffer);
- }
-}
diff --git a/services/net/java/android/net/netlink/InetDiagMessage.java b/services/net/java/android/net/netlink/InetDiagMessage.java
deleted file mode 100644
index ca07630..0000000
--- a/services/net/java/android/net/netlink/InetDiagMessage.java
+++ /dev/null
@@ -1,221 +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 android.net.netlink;
-
-import static android.net.netlink.NetlinkConstants.SOCK_DIAG_BY_FAMILY;
-import static android.net.netlink.NetlinkSocket.DEFAULT_RECV_BUFSIZE;
-import static android.net.netlink.StructNlMsgHdr.NLM_F_DUMP;
-import static android.net.netlink.StructNlMsgHdr.NLM_F_REQUEST;
-import static android.os.Process.INVALID_UID;
-import static android.system.OsConstants.AF_INET;
-import static android.system.OsConstants.AF_INET6;
-import static android.system.OsConstants.IPPROTO_UDP;
-import static android.system.OsConstants.NETLINK_INET_DIAG;
-
-import android.annotation.Nullable;
-import android.net.util.SocketUtils;
-import android.system.ErrnoException;
-import android.util.Log;
-
-import java.io.FileDescriptor;
-import java.io.IOException;
-import java.io.InterruptedIOException;
-import java.net.Inet4Address;
-import java.net.Inet6Address;
-import java.net.InetSocketAddress;
-import java.net.SocketException;
-import java.net.UnknownHostException;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-
-/**
- * A NetlinkMessage subclass for netlink inet_diag messages.
- *
- * see also: <linux_src>/include/uapi/linux/inet_diag.h
- *
- * @hide
- */
-public class InetDiagMessage extends NetlinkMessage {
- public static final String TAG = "InetDiagMessage";
- private static final int TIMEOUT_MS = 500;
-
- public static byte[] InetDiagReqV2(int protocol, InetSocketAddress local,
- InetSocketAddress remote, int family, short flags) {
- return InetDiagReqV2(protocol, local, remote, family, flags, 0 /* pad */,
- 0 /* idiagExt */, StructInetDiagReqV2.INET_DIAG_REQ_V2_ALL_STATES);
- }
-
- /**
- * Construct an inet_diag_req_v2 message. This method will throw {@code NullPointerException}
- * if local and remote are not both null or both non-null.
- *
- * @param protocol the request protocol type. This should be set to one of IPPROTO_TCP,
- * IPPROTO_UDP, or IPPROTO_UDPLITE.
- * @param local local socket address of the target socket. This will be packed into a
- * {@Code StructInetDiagSockId}. Request to diagnose for all sockets if both of
- * local or remote address is null.
- * @param remote remote socket address of the target socket. This will be packed into a
- * {@Code StructInetDiagSockId}. Request to diagnose for all sockets if both of
- * local or remote address is null.
- * @param family the ip family of the request message. This should be set to either AF_INET or
- * AF_INET6 for IPv4 or IPv6 sockets respectively.
- * @param flags message flags. See <linux_src>/include/uapi/linux/netlink.h.
- * @param pad for raw socket protocol specification.
- * @param idiagExt a set of flags defining what kind of extended information to report.
- * @param state a bit mask that defines a filter of socket states.
- *
- * @return bytes array representation of the message
- **/
- public static byte[] InetDiagReqV2(int protocol, @Nullable InetSocketAddress local,
- @Nullable InetSocketAddress remote, int family, short flags, int pad, int idiagExt,
- int state) throws NullPointerException {
- final byte[] bytes = new byte[StructNlMsgHdr.STRUCT_SIZE + StructInetDiagReqV2.STRUCT_SIZE];
- final ByteBuffer byteBuffer = ByteBuffer.wrap(bytes);
- byteBuffer.order(ByteOrder.nativeOrder());
-
- final StructNlMsgHdr nlMsgHdr = new StructNlMsgHdr();
- nlMsgHdr.nlmsg_len = bytes.length;
- nlMsgHdr.nlmsg_type = SOCK_DIAG_BY_FAMILY;
- nlMsgHdr.nlmsg_flags = flags;
- nlMsgHdr.pack(byteBuffer);
- final StructInetDiagReqV2 inetDiagReqV2 =
- new StructInetDiagReqV2(protocol, local, remote, family, pad, idiagExt, state);
-
- inetDiagReqV2.pack(byteBuffer);
- return bytes;
- }
-
- public StructInetDiagMsg mStructInetDiagMsg;
-
- private InetDiagMessage(StructNlMsgHdr header) {
- super(header);
- mStructInetDiagMsg = new StructInetDiagMsg();
- }
-
- public static InetDiagMessage parse(StructNlMsgHdr header, ByteBuffer byteBuffer) {
- final InetDiagMessage msg = new InetDiagMessage(header);
- msg.mStructInetDiagMsg = StructInetDiagMsg.parse(byteBuffer);
- return msg;
- }
-
- private static int lookupUidByFamily(int protocol, InetSocketAddress local,
- InetSocketAddress remote, int family, short flags,
- FileDescriptor fd)
- throws ErrnoException, InterruptedIOException {
- byte[] msg = InetDiagReqV2(protocol, local, remote, family, flags);
- NetlinkSocket.sendMessage(fd, msg, 0, msg.length, TIMEOUT_MS);
- ByteBuffer response = NetlinkSocket.recvMessage(fd, DEFAULT_RECV_BUFSIZE, TIMEOUT_MS);
-
- final NetlinkMessage nlMsg = NetlinkMessage.parse(response);
- final StructNlMsgHdr hdr = nlMsg.getHeader();
- if (hdr.nlmsg_type == NetlinkConstants.NLMSG_DONE) {
- return INVALID_UID;
- }
- if (nlMsg instanceof InetDiagMessage) {
- return ((InetDiagMessage) nlMsg).mStructInetDiagMsg.idiag_uid;
- }
- return INVALID_UID;
- }
-
- private static final int FAMILY[] = {AF_INET6, AF_INET};
-
- private static int lookupUid(int protocol, InetSocketAddress local,
- InetSocketAddress remote, FileDescriptor fd)
- throws ErrnoException, InterruptedIOException {
- int uid;
-
- for (int family : FAMILY) {
- /**
- * For exact match lookup, swap local and remote for UDP lookups due to kernel
- * bug which will not be fixed. See aosp/755889 and
- * https://www.mail-archive.com/netdev@vger.kernel.org/msg248638.html
- */
- if (protocol == IPPROTO_UDP) {
- uid = lookupUidByFamily(protocol, remote, local, family, NLM_F_REQUEST, fd);
- } else {
- uid = lookupUidByFamily(protocol, local, remote, family, NLM_F_REQUEST, fd);
- }
- if (uid != INVALID_UID) {
- return uid;
- }
- }
-
- /**
- * For UDP it's possible for a socket to send packets to arbitrary destinations, even if the
- * socket is not connected (and even if the socket is connected to a different destination).
- * If we want this API to work for such packets, then on miss we need to do a second lookup
- * with only the local address and port filled in.
- * Always use flags == NLM_F_REQUEST | NLM_F_DUMP for wildcard.
- */
- if (protocol == IPPROTO_UDP) {
- try {
- InetSocketAddress wildcard = new InetSocketAddress(
- Inet6Address.getByName("::"), 0);
- uid = lookupUidByFamily(protocol, local, wildcard, AF_INET6,
- (short) (NLM_F_REQUEST | NLM_F_DUMP), fd);
- if (uid != INVALID_UID) {
- return uid;
- }
- wildcard = new InetSocketAddress(Inet4Address.getByName("0.0.0.0"), 0);
- uid = lookupUidByFamily(protocol, local, wildcard, AF_INET,
- (short) (NLM_F_REQUEST | NLM_F_DUMP), fd);
- if (uid != INVALID_UID) {
- return uid;
- }
- } catch (UnknownHostException e) {
- Log.e(TAG, e.toString());
- }
- }
- return INVALID_UID;
- }
-
- /**
- * Use an inet_diag socket to look up the UID associated with the input local and remote
- * address/port and protocol of a connection.
- */
- public static int getConnectionOwnerUid(int protocol, InetSocketAddress local,
- InetSocketAddress remote) {
- int uid = INVALID_UID;
- FileDescriptor fd = null;
- try {
- fd = NetlinkSocket.forProto(NETLINK_INET_DIAG);
- NetlinkSocket.connectToKernel(fd);
- uid = lookupUid(protocol, local, remote, fd);
- } catch (ErrnoException | SocketException | IllegalArgumentException
- | InterruptedIOException e) {
- Log.e(TAG, e.toString());
- } finally {
- if (fd != null) {
- try {
- SocketUtils.closeSocket(fd);
- } catch (IOException e) {
- Log.e(TAG, e.toString());
- }
- }
- }
- return uid;
- }
-
- @Override
- public String toString() {
- return "InetDiagMessage{ "
- + "nlmsghdr{" + (mHeader == null ? "" : mHeader.toString()) + "}, "
- + "inet_diag_msg{"
- + (mStructInetDiagMsg == null ? "" : mStructInetDiagMsg.toString()) + "} "
- + "}";
- }
-}
diff --git a/services/net/java/android/net/netlink/NetlinkConstants.java b/services/net/java/android/net/netlink/NetlinkConstants.java
deleted file mode 100644
index fc1551c..0000000
--- a/services/net/java/android/net/netlink/NetlinkConstants.java
+++ /dev/null
@@ -1,129 +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 android.net.netlink;
-
-import android.system.OsConstants;
-import com.android.internal.util.HexDump;
-
-import java.nio.ByteBuffer;
-
-
-/**
- * Various constants and static helper methods for netlink communications.
- *
- * Values taken from:
- *
- * <linux_src>/include/uapi/linux/netlink.h
- * <linux_src>/include/uapi/linux/rtnetlink.h
- *
- * @hide
- */
-public class NetlinkConstants {
- private NetlinkConstants() {}
-
- public static final int NLA_ALIGNTO = 4;
-
- public static final int alignedLengthOf(short length) {
- final int intLength = (int) length & 0xffff;
- return alignedLengthOf(intLength);
- }
-
- public static final int alignedLengthOf(int length) {
- if (length <= 0) { return 0; }
- return (((length + NLA_ALIGNTO - 1) / NLA_ALIGNTO) * NLA_ALIGNTO);
- }
-
- public static String stringForAddressFamily(int family) {
- if (family == OsConstants.AF_INET) { return "AF_INET"; }
- if (family == OsConstants.AF_INET6) { return "AF_INET6"; }
- if (family == OsConstants.AF_NETLINK) { return "AF_NETLINK"; }
- return String.valueOf(family);
- }
-
- public static String stringForProtocol(int protocol) {
- if (protocol == OsConstants.IPPROTO_TCP) { return "IPPROTO_TCP"; }
- if (protocol == OsConstants.IPPROTO_UDP) { return "IPPROTO_UDP"; }
- return String.valueOf(protocol);
- }
-
- public static String hexify(byte[] bytes) {
- if (bytes == null) { return "(null)"; }
- return HexDump.toHexString(bytes);
- }
-
- public static String hexify(ByteBuffer buffer) {
- if (buffer == null) { return "(null)"; }
- return HexDump.toHexString(
- buffer.array(), buffer.position(), buffer.remaining());
- }
-
- // Known values for struct nlmsghdr nlm_type.
- public static final short NLMSG_NOOP = 1; // Nothing
- public static final short NLMSG_ERROR = 2; // Error
- public static final short NLMSG_DONE = 3; // End of a dump
- public static final short NLMSG_OVERRUN = 4; // Data lost
- public static final short NLMSG_MAX_RESERVED = 15; // Max reserved value
-
- public static final short RTM_NEWLINK = 16;
- public static final short RTM_DELLINK = 17;
- public static final short RTM_GETLINK = 18;
- public static final short RTM_SETLINK = 19;
- public static final short RTM_NEWADDR = 20;
- public static final short RTM_DELADDR = 21;
- public static final short RTM_GETADDR = 22;
- public static final short RTM_NEWROUTE = 24;
- public static final short RTM_DELROUTE = 25;
- public static final short RTM_GETROUTE = 26;
- public static final short RTM_NEWNEIGH = 28;
- public static final short RTM_DELNEIGH = 29;
- public static final short RTM_GETNEIGH = 30;
- public static final short RTM_NEWRULE = 32;
- public static final short RTM_DELRULE = 33;
- public static final short RTM_GETRULE = 34;
- public static final short RTM_NEWNDUSEROPT = 68;
-
- /* see <linux_src>/include/uapi/linux/sock_diag.h */
- public static final short SOCK_DIAG_BY_FAMILY = 20;
-
- public static String stringForNlMsgType(short nlm_type) {
- switch (nlm_type) {
- case NLMSG_NOOP: return "NLMSG_NOOP";
- case NLMSG_ERROR: return "NLMSG_ERROR";
- case NLMSG_DONE: return "NLMSG_DONE";
- case NLMSG_OVERRUN: return "NLMSG_OVERRUN";
- case RTM_NEWLINK: return "RTM_NEWLINK";
- case RTM_DELLINK: return "RTM_DELLINK";
- case RTM_GETLINK: return "RTM_GETLINK";
- case RTM_SETLINK: return "RTM_SETLINK";
- case RTM_NEWADDR: return "RTM_NEWADDR";
- case RTM_DELADDR: return "RTM_DELADDR";
- case RTM_GETADDR: return "RTM_GETADDR";
- case RTM_NEWROUTE: return "RTM_NEWROUTE";
- case RTM_DELROUTE: return "RTM_DELROUTE";
- case RTM_GETROUTE: return "RTM_GETROUTE";
- case RTM_NEWNEIGH: return "RTM_NEWNEIGH";
- case RTM_DELNEIGH: return "RTM_DELNEIGH";
- case RTM_GETNEIGH: return "RTM_GETNEIGH";
- case RTM_NEWRULE: return "RTM_NEWRULE";
- case RTM_DELRULE: return "RTM_DELRULE";
- case RTM_GETRULE: return "RTM_GETRULE";
- case RTM_NEWNDUSEROPT: return "RTM_NEWNDUSEROPT";
- default:
- return "unknown RTM type: " + String.valueOf(nlm_type);
- }
- }
-}
diff --git a/services/net/java/android/net/netlink/NetlinkErrorMessage.java b/services/net/java/android/net/netlink/NetlinkErrorMessage.java
deleted file mode 100644
index e275574..0000000
--- a/services/net/java/android/net/netlink/NetlinkErrorMessage.java
+++ /dev/null
@@ -1,61 +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 android.net.netlink;
-
-import android.net.netlink.StructNlMsgHdr;
-import android.net.netlink.NetlinkMessage;
-
-import java.nio.ByteBuffer;
-
-
-/**
- * A NetlinkMessage subclass for netlink error messages.
- *
- * @hide
- */
-public class NetlinkErrorMessage extends NetlinkMessage {
-
- public static NetlinkErrorMessage parse(StructNlMsgHdr header, ByteBuffer byteBuffer) {
- final NetlinkErrorMessage errorMsg = new NetlinkErrorMessage(header);
-
- errorMsg.mNlMsgErr = StructNlMsgErr.parse(byteBuffer);
- if (errorMsg.mNlMsgErr == null) {
- return null;
- }
-
- return errorMsg;
- }
-
- private StructNlMsgErr mNlMsgErr;
-
- NetlinkErrorMessage(StructNlMsgHdr header) {
- super(header);
- mNlMsgErr = null;
- }
-
- public StructNlMsgErr getNlMsgError() {
- return mNlMsgErr;
- }
-
- @Override
- public String toString() {
- return "NetlinkErrorMessage{ "
- + "nlmsghdr{" + (mHeader == null ? "" : mHeader.toString()) + "}, "
- + "nlmsgerr{" + (mNlMsgErr == null ? "" : mNlMsgErr.toString()) + "} "
- + "}";
- }
-}
diff --git a/services/net/java/android/net/netlink/NetlinkMessage.java b/services/net/java/android/net/netlink/NetlinkMessage.java
deleted file mode 100644
index a325db8..0000000
--- a/services/net/java/android/net/netlink/NetlinkMessage.java
+++ /dev/null
@@ -1,99 +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 android.net.netlink;
-
-import android.net.netlink.NetlinkConstants;
-import android.net.netlink.NetlinkErrorMessage;
-import android.net.netlink.RtNetlinkNeighborMessage;
-import android.net.netlink.StructNlAttr;
-import android.net.netlink.StructNlMsgHdr;
-import android.util.Log;
-
-import java.nio.ByteBuffer;
-
-
-/**
- * NetlinkMessage base class for other, more specific netlink message types.
- *
- * Classes that extend NetlinkMessage should:
- * - implement a public static parse(StructNlMsgHdr, ByteBuffer) method
- * - returning either null (parse errors) or a new object of the subclass
- * type (cast-able to NetlinkMessage)
- *
- * NetlinkMessage.parse() should be updated to know which nlmsg_type values
- * correspond with which message subclasses.
- *
- * @hide
- */
-public class NetlinkMessage {
- private final static String TAG = "NetlinkMessage";
-
- public static NetlinkMessage parse(ByteBuffer byteBuffer) {
- final int startPosition = (byteBuffer != null) ? byteBuffer.position() : -1;
- final StructNlMsgHdr nlmsghdr = StructNlMsgHdr.parse(byteBuffer);
- if (nlmsghdr == null) {
- return null;
- }
-
- int payloadLength = NetlinkConstants.alignedLengthOf(nlmsghdr.nlmsg_len);
- payloadLength -= StructNlMsgHdr.STRUCT_SIZE;
- if (payloadLength < 0 || payloadLength > byteBuffer.remaining()) {
- // Malformed message or runt buffer. Pretend the buffer was consumed.
- byteBuffer.position(byteBuffer.limit());
- return null;
- }
-
- switch (nlmsghdr.nlmsg_type) {
- //case NetlinkConstants.NLMSG_NOOP:
- case NetlinkConstants.NLMSG_ERROR:
- return (NetlinkMessage) NetlinkErrorMessage.parse(nlmsghdr, byteBuffer);
- case NetlinkConstants.NLMSG_DONE:
- byteBuffer.position(byteBuffer.position() + payloadLength);
- return new NetlinkMessage(nlmsghdr);
- //case NetlinkConstants.NLMSG_OVERRUN:
- case NetlinkConstants.RTM_NEWNEIGH:
- case NetlinkConstants.RTM_DELNEIGH:
- case NetlinkConstants.RTM_GETNEIGH:
- return (NetlinkMessage) RtNetlinkNeighborMessage.parse(nlmsghdr, byteBuffer);
- case NetlinkConstants.SOCK_DIAG_BY_FAMILY:
- return (NetlinkMessage) InetDiagMessage.parse(nlmsghdr, byteBuffer);
- default:
- if (nlmsghdr.nlmsg_type <= NetlinkConstants.NLMSG_MAX_RESERVED) {
- // Netlink control message. Just parse the header for now,
- // pretending the whole message was consumed.
- byteBuffer.position(byteBuffer.position() + payloadLength);
- return new NetlinkMessage(nlmsghdr);
- }
- return null;
- }
- }
-
- protected StructNlMsgHdr mHeader;
-
- public NetlinkMessage(StructNlMsgHdr nlmsghdr) {
- mHeader = nlmsghdr;
- }
-
- public StructNlMsgHdr getHeader() {
- return mHeader;
- }
-
- @Override
- public String toString() {
- return "NetlinkMessage{" + (mHeader == null ? "" : mHeader.toString()) + "}";
- }
-}
diff --git a/services/net/java/android/net/netlink/NetlinkSocket.java b/services/net/java/android/net/netlink/NetlinkSocket.java
deleted file mode 100644
index 7311fc5..0000000
--- a/services/net/java/android/net/netlink/NetlinkSocket.java
+++ /dev/null
@@ -1,158 +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 android.net.netlink;
-
-import static android.net.util.SocketUtils.makeNetlinkSocketAddress;
-import static android.system.OsConstants.AF_NETLINK;
-import static android.system.OsConstants.EIO;
-import static android.system.OsConstants.EPROTO;
-import static android.system.OsConstants.ETIMEDOUT;
-import static android.system.OsConstants.SOCK_DGRAM;
-import static android.system.OsConstants.SOL_SOCKET;
-import static android.system.OsConstants.SO_RCVBUF;
-import static android.system.OsConstants.SO_RCVTIMEO;
-import static android.system.OsConstants.SO_SNDTIMEO;
-
-import android.net.util.SocketUtils;
-import android.system.ErrnoException;
-import android.system.Os;
-import android.system.StructTimeval;
-import android.util.Log;
-
-import java.io.FileDescriptor;
-import java.io.IOException;
-import java.io.InterruptedIOException;
-import java.net.SocketException;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-
-
-/**
- * NetlinkSocket
- *
- * A small static class to assist with AF_NETLINK socket operations.
- *
- * @hide
- */
-public class NetlinkSocket {
- private static final String TAG = "NetlinkSocket";
-
- public static final int DEFAULT_RECV_BUFSIZE = 8 * 1024;
- public static final int SOCKET_RECV_BUFSIZE = 64 * 1024;
-
- public static void sendOneShotKernelMessage(int nlProto, byte[] msg) throws ErrnoException {
- final String errPrefix = "Error in NetlinkSocket.sendOneShotKernelMessage";
- final long IO_TIMEOUT = 300L;
-
- final FileDescriptor fd = forProto(nlProto);
-
- try {
- connectToKernel(fd);
- sendMessage(fd, msg, 0, msg.length, IO_TIMEOUT);
- final ByteBuffer bytes = recvMessage(fd, DEFAULT_RECV_BUFSIZE, IO_TIMEOUT);
- // recvMessage() guaranteed to not return null if it did not throw.
- final NetlinkMessage response = NetlinkMessage.parse(bytes);
- if (response != null && response instanceof NetlinkErrorMessage &&
- (((NetlinkErrorMessage) response).getNlMsgError() != null)) {
- final int errno = ((NetlinkErrorMessage) response).getNlMsgError().error;
- if (errno != 0) {
- // TODO: consider ignoring EINVAL (-22), which appears to be
- // normal when probing a neighbor for which the kernel does
- // not already have / no longer has a link layer address.
- Log.e(TAG, errPrefix + ", errmsg=" + response.toString());
- // Note: convert kernel errnos (negative) into userspace errnos (positive).
- throw new ErrnoException(response.toString(), Math.abs(errno));
- }
- } else {
- final String errmsg;
- if (response == null) {
- bytes.position(0);
- errmsg = "raw bytes: " + NetlinkConstants.hexify(bytes);
- } else {
- errmsg = response.toString();
- }
- Log.e(TAG, errPrefix + ", errmsg=" + errmsg);
- throw new ErrnoException(errmsg, EPROTO);
- }
- } catch (InterruptedIOException e) {
- Log.e(TAG, errPrefix, e);
- throw new ErrnoException(errPrefix, ETIMEDOUT, e);
- } catch (SocketException e) {
- Log.e(TAG, errPrefix, e);
- throw new ErrnoException(errPrefix, EIO, e);
- } finally {
- try {
- SocketUtils.closeSocket(fd);
- } catch (IOException e) {
- // Nothing we can do here
- }
- }
- }
-
- public static FileDescriptor forProto(int nlProto) throws ErrnoException {
- final FileDescriptor fd = Os.socket(AF_NETLINK, SOCK_DGRAM, nlProto);
- Os.setsockoptInt(fd, SOL_SOCKET, SO_RCVBUF, SOCKET_RECV_BUFSIZE);
- return fd;
- }
-
- public static void connectToKernel(FileDescriptor fd) throws ErrnoException, SocketException {
- Os.connect(fd, makeNetlinkSocketAddress(0, 0));
- }
-
- private static void checkTimeout(long timeoutMs) {
- if (timeoutMs < 0) {
- throw new IllegalArgumentException("Negative timeouts not permitted");
- }
- }
-
- /**
- * Wait up to |timeoutMs| (or until underlying socket error) for a
- * netlink message of at most |bufsize| size.
- *
- * Multi-threaded calls with different timeouts will cause unexpected results.
- */
- public static ByteBuffer recvMessage(FileDescriptor fd, int bufsize, long timeoutMs)
- throws ErrnoException, IllegalArgumentException, InterruptedIOException {
- checkTimeout(timeoutMs);
-
- Os.setsockoptTimeval(fd, SOL_SOCKET, SO_RCVTIMEO, StructTimeval.fromMillis(timeoutMs));
-
- ByteBuffer byteBuffer = ByteBuffer.allocate(bufsize);
- int length = Os.read(fd, byteBuffer);
- if (length == bufsize) {
- Log.w(TAG, "maximum read");
- }
- byteBuffer.position(0);
- byteBuffer.limit(length);
- byteBuffer.order(ByteOrder.nativeOrder());
- return byteBuffer;
- }
-
- /**
- * Send a message to a peer to which this socket has previously connected,
- * waiting at most |timeoutMs| milliseconds for the send to complete.
- *
- * Multi-threaded calls with different timeouts will cause unexpected results.
- */
- public static int sendMessage(
- FileDescriptor fd, byte[] bytes, int offset, int count, long timeoutMs)
- throws ErrnoException, IllegalArgumentException, InterruptedIOException {
- checkTimeout(timeoutMs);
- Os.setsockoptTimeval(fd, SOL_SOCKET, SO_SNDTIMEO, StructTimeval.fromMillis(timeoutMs));
- return Os.write(fd, bytes, offset, count);
- }
-}
diff --git a/services/net/java/android/net/netlink/RtNetlinkNeighborMessage.java b/services/net/java/android/net/netlink/RtNetlinkNeighborMessage.java
deleted file mode 100644
index e784fbb..0000000
--- a/services/net/java/android/net/netlink/RtNetlinkNeighborMessage.java
+++ /dev/null
@@ -1,251 +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 android.net.netlink;
-
-import static android.net.netlink.StructNlMsgHdr.NLM_F_ACK;
-import static android.net.netlink.StructNlMsgHdr.NLM_F_DUMP;
-import static android.net.netlink.StructNlMsgHdr.NLM_F_REPLACE;
-import static android.net.netlink.StructNlMsgHdr.NLM_F_REQUEST;
-
-import android.net.netlink.StructNdaCacheInfo;
-import android.net.netlink.StructNdMsg;
-import android.net.netlink.StructNlAttr;
-import android.net.netlink.StructNlMsgHdr;
-import android.net.netlink.NetlinkMessage;
-import android.system.OsConstants;
-import android.util.Log;
-
-import java.net.InetAddress;
-import java.net.Inet6Address;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-
-
-/**
- * A NetlinkMessage subclass for rtnetlink neighbor messages.
- *
- * see also: <linux_src>/include/uapi/linux/neighbour.h
- *
- * @hide
- */
-public class RtNetlinkNeighborMessage extends NetlinkMessage {
- public static final short NDA_UNSPEC = 0;
- public static final short NDA_DST = 1;
- public static final short NDA_LLADDR = 2;
- public static final short NDA_CACHEINFO = 3;
- public static final short NDA_PROBES = 4;
- public static final short NDA_VLAN = 5;
- public static final short NDA_PORT = 6;
- public static final short NDA_VNI = 7;
- public static final short NDA_IFINDEX = 8;
- public static final short NDA_MASTER = 9;
-
- private static StructNlAttr findNextAttrOfType(short attrType, ByteBuffer byteBuffer) {
- while (byteBuffer != null && byteBuffer.remaining() > 0) {
- final StructNlAttr nlAttr = StructNlAttr.peek(byteBuffer);
- if (nlAttr == null) {
- break;
- }
- if (nlAttr.nla_type == attrType) {
- return StructNlAttr.parse(byteBuffer);
- }
- if (byteBuffer.remaining() < nlAttr.getAlignedLength()) {
- break;
- }
- byteBuffer.position(byteBuffer.position() + nlAttr.getAlignedLength());
- }
- return null;
- }
-
- public static RtNetlinkNeighborMessage parse(StructNlMsgHdr header, ByteBuffer byteBuffer) {
- final RtNetlinkNeighborMessage neighMsg = new RtNetlinkNeighborMessage(header);
-
- neighMsg.mNdmsg = StructNdMsg.parse(byteBuffer);
- if (neighMsg.mNdmsg == null) {
- return null;
- }
-
- // Some of these are message-type dependent, and not always present.
- final int baseOffset = byteBuffer.position();
- StructNlAttr nlAttr = findNextAttrOfType(NDA_DST, byteBuffer);
- if (nlAttr != null) {
- neighMsg.mDestination = nlAttr.getValueAsInetAddress();
- }
-
- byteBuffer.position(baseOffset);
- nlAttr = findNextAttrOfType(NDA_LLADDR, byteBuffer);
- if (nlAttr != null) {
- neighMsg.mLinkLayerAddr = nlAttr.nla_value;
- }
-
- byteBuffer.position(baseOffset);
- nlAttr = findNextAttrOfType(NDA_PROBES, byteBuffer);
- if (nlAttr != null) {
- neighMsg.mNumProbes = nlAttr.getValueAsInt(0);
- }
-
- byteBuffer.position(baseOffset);
- nlAttr = findNextAttrOfType(NDA_CACHEINFO, byteBuffer);
- if (nlAttr != null) {
- neighMsg.mCacheInfo = StructNdaCacheInfo.parse(nlAttr.getValueAsByteBuffer());
- }
-
- final int kMinConsumed = StructNlMsgHdr.STRUCT_SIZE + StructNdMsg.STRUCT_SIZE;
- final int kAdditionalSpace = NetlinkConstants.alignedLengthOf(
- neighMsg.mHeader.nlmsg_len - kMinConsumed);
- if (byteBuffer.remaining() < kAdditionalSpace) {
- byteBuffer.position(byteBuffer.limit());
- } else {
- byteBuffer.position(baseOffset + kAdditionalSpace);
- }
-
- return neighMsg;
- }
-
- /**
- * A convenience method to create an RTM_GETNEIGH request message.
- */
- public static byte[] newGetNeighborsRequest(int seqNo) {
- final int length = StructNlMsgHdr.STRUCT_SIZE + StructNdMsg.STRUCT_SIZE;
- final byte[] bytes = new byte[length];
- final ByteBuffer byteBuffer = ByteBuffer.wrap(bytes);
- byteBuffer.order(ByteOrder.nativeOrder());
-
- final StructNlMsgHdr nlmsghdr = new StructNlMsgHdr();
- nlmsghdr.nlmsg_len = length;
- nlmsghdr.nlmsg_type = NetlinkConstants.RTM_GETNEIGH;
- nlmsghdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
- nlmsghdr.nlmsg_seq = seqNo;
- nlmsghdr.pack(byteBuffer);
-
- final StructNdMsg ndmsg = new StructNdMsg();
- ndmsg.pack(byteBuffer);
-
- return bytes;
- }
-
- /**
- * A convenience method to create an RTM_NEWNEIGH message, to modify
- * the kernel's state information for a specific neighbor.
- */
- public static byte[] newNewNeighborMessage(
- int seqNo, InetAddress ip, short nudState, int ifIndex, byte[] llAddr) {
- final StructNlMsgHdr nlmsghdr = new StructNlMsgHdr();
- nlmsghdr.nlmsg_type = NetlinkConstants.RTM_NEWNEIGH;
- nlmsghdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_REPLACE;
- nlmsghdr.nlmsg_seq = seqNo;
-
- final RtNetlinkNeighborMessage msg = new RtNetlinkNeighborMessage(nlmsghdr);
- msg.mNdmsg = new StructNdMsg();
- msg.mNdmsg.ndm_family =
- (byte) ((ip instanceof Inet6Address) ? OsConstants.AF_INET6 : OsConstants.AF_INET);
- msg.mNdmsg.ndm_ifindex = ifIndex;
- msg.mNdmsg.ndm_state = nudState;
- msg.mDestination = ip;
- msg.mLinkLayerAddr = llAddr; // might be null
-
- final byte[] bytes = new byte[msg.getRequiredSpace()];
- nlmsghdr.nlmsg_len = bytes.length;
- final ByteBuffer byteBuffer = ByteBuffer.wrap(bytes);
- byteBuffer.order(ByteOrder.nativeOrder());
- msg.pack(byteBuffer);
- return bytes;
- }
-
- private StructNdMsg mNdmsg;
- private InetAddress mDestination;
- private byte[] mLinkLayerAddr;
- private int mNumProbes;
- private StructNdaCacheInfo mCacheInfo;
-
- private RtNetlinkNeighborMessage(StructNlMsgHdr header) {
- super(header);
- mNdmsg = null;
- mDestination = null;
- mLinkLayerAddr = null;
- mNumProbes = 0;
- mCacheInfo = null;
- }
-
- public StructNdMsg getNdHeader() {
- return mNdmsg;
- }
-
- public InetAddress getDestination() {
- return mDestination;
- }
-
- public byte[] getLinkLayerAddress() {
- return mLinkLayerAddr;
- }
-
- public int getProbes() {
- return mNumProbes;
- }
-
- public StructNdaCacheInfo getCacheInfo() {
- return mCacheInfo;
- }
-
- public int getRequiredSpace() {
- int spaceRequired = StructNlMsgHdr.STRUCT_SIZE + StructNdMsg.STRUCT_SIZE;
- if (mDestination != null) {
- spaceRequired += NetlinkConstants.alignedLengthOf(
- StructNlAttr.NLA_HEADERLEN + mDestination.getAddress().length);
- }
- if (mLinkLayerAddr != null) {
- spaceRequired += NetlinkConstants.alignedLengthOf(
- StructNlAttr.NLA_HEADERLEN + mLinkLayerAddr.length);
- }
- // Currently we don't write messages with NDA_PROBES nor NDA_CACHEINFO
- // attributes appended. Fix later, if necessary.
- return spaceRequired;
- }
-
- private static void packNlAttr(short nlType, byte[] nlValue, ByteBuffer byteBuffer) {
- final StructNlAttr nlAttr = new StructNlAttr();
- nlAttr.nla_type = nlType;
- nlAttr.nla_value = nlValue;
- nlAttr.nla_len = (short) (StructNlAttr.NLA_HEADERLEN + nlAttr.nla_value.length);
- nlAttr.pack(byteBuffer);
- }
-
- public void pack(ByteBuffer byteBuffer) {
- getHeader().pack(byteBuffer) ;
- mNdmsg.pack(byteBuffer);
-
- if (mDestination != null) {
- packNlAttr(NDA_DST, mDestination.getAddress(), byteBuffer);
- }
- if (mLinkLayerAddr != null) {
- packNlAttr(NDA_LLADDR, mLinkLayerAddr, byteBuffer);
- }
- }
-
- @Override
- public String toString() {
- final String ipLiteral = (mDestination == null) ? "" : mDestination.getHostAddress();
- return "RtNetlinkNeighborMessage{ "
- + "nlmsghdr{" + (mHeader == null ? "" : mHeader.toString()) + "}, "
- + "ndmsg{" + (mNdmsg == null ? "" : mNdmsg.toString()) + "}, "
- + "destination{" + ipLiteral + "} "
- + "linklayeraddr{" + NetlinkConstants.hexify(mLinkLayerAddr) + "} "
- + "probes{" + mNumProbes + "} "
- + "cacheinfo{" + (mCacheInfo == null ? "" : mCacheInfo.toString()) + "} "
- + "}";
- }
-}
diff --git a/services/net/java/android/net/netlink/StructInetDiagMsg.java b/services/net/java/android/net/netlink/StructInetDiagMsg.java
deleted file mode 100644
index da824ad..0000000
--- a/services/net/java/android/net/netlink/StructInetDiagMsg.java
+++ /dev/null
@@ -1,67 +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 android.net.netlink;
-
-import static java.nio.ByteOrder.BIG_ENDIAN;
-import static android.system.OsConstants.AF_INET;
-import static android.system.OsConstants.AF_INET6;
-
-import java.net.Inet4Address;
-import java.net.InetSocketAddress;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-import android.util.Log;
-
-/**
- * struct inet_diag_msg
- *
- * see <linux_src>/include/uapi/linux/inet_diag.h
- *
- * struct inet_diag_msg {
- * __u8 idiag_family;
- * __u8 idiag_state;
- * __u8 idiag_timer;
- * __u8 idiag_retrans;
- * struct inet_diag_sockid id;
- * __u32 idiag_expires;
- * __u32 idiag_rqueue;
- * __u32 idiag_wqueue;
- * __u32 idiag_uid;
- * __u32 idiag_inode;
- * };
- *
- * @hide
- */
-public class StructInetDiagMsg {
- public static final int STRUCT_SIZE = 4 + StructInetDiagSockId.STRUCT_SIZE + 20;
- private static final int IDIAG_UID_OFFSET = StructNlMsgHdr.STRUCT_SIZE + 4 +
- StructInetDiagSockId.STRUCT_SIZE + 12;
- public int idiag_uid;
-
- public static StructInetDiagMsg parse(ByteBuffer byteBuffer) {
- StructInetDiagMsg struct = new StructInetDiagMsg();
- struct.idiag_uid = byteBuffer.getInt(IDIAG_UID_OFFSET);
- return struct;
- }
-
- @Override
- public String toString() {
- return "StructInetDiagMsg{ "
- + "idiag_uid{" + idiag_uid + "}, "
- + "}";
- }
-}
diff --git a/services/net/java/android/net/netlink/StructInetDiagReqV2.java b/services/net/java/android/net/netlink/StructInetDiagReqV2.java
deleted file mode 100644
index 2268113..0000000
--- a/services/net/java/android/net/netlink/StructInetDiagReqV2.java
+++ /dev/null
@@ -1,97 +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 android.net.netlink;
-
-import android.annotation.Nullable;
-
-import java.net.InetSocketAddress;
-import java.nio.ByteBuffer;
-
-/**
- * struct inet_diag_req_v2
- *
- * see <linux_src>/include/uapi/linux/inet_diag.h
- *
- * struct inet_diag_req_v2 {
- * __u8 sdiag_family;
- * __u8 sdiag_protocol;
- * __u8 idiag_ext;
- * __u8 pad;
- * __u32 idiag_states;
- * struct inet_diag_sockid id;
- * };
- *
- * @hide
- */
-public class StructInetDiagReqV2 {
- public static final int STRUCT_SIZE = 8 + StructInetDiagSockId.STRUCT_SIZE;
-
- private final byte mSdiagFamily;
- private final byte mSdiagProtocol;
- private final byte mIdiagExt;
- private final byte mPad;
- private final StructInetDiagSockId mId;
- private final int mState;
- public static final int INET_DIAG_REQ_V2_ALL_STATES = (int) 0xffffffff;
-
- public StructInetDiagReqV2(int protocol, InetSocketAddress local, InetSocketAddress remote,
- int family) {
- this(protocol, local, remote, family, 0 /* pad */, 0 /* extension */,
- INET_DIAG_REQ_V2_ALL_STATES);
- }
-
- public StructInetDiagReqV2(int protocol, @Nullable InetSocketAddress local,
- @Nullable InetSocketAddress remote, int family, int pad, int extension, int state)
- throws NullPointerException {
- mSdiagFamily = (byte) family;
- mSdiagProtocol = (byte) protocol;
- // Request for all sockets if no specific socket is requested. Specify the local and remote
- // socket address information for target request socket.
- if ((local == null) != (remote == null)) {
- throw new NullPointerException("Local and remote must be both null or both non-null");
- }
- mId = ((local != null && remote != null) ? new StructInetDiagSockId(local, remote) : null);
- mPad = (byte) pad;
- mIdiagExt = (byte) extension;
- mState = state;
- }
-
- public void pack(ByteBuffer byteBuffer) {
- // The ByteOrder must have already been set by the caller.
- byteBuffer.put((byte) mSdiagFamily);
- byteBuffer.put((byte) mSdiagProtocol);
- byteBuffer.put((byte) mIdiagExt);
- byteBuffer.put((byte) mPad);
- byteBuffer.putInt(mState);
- if (mId != null) mId.pack(byteBuffer);
- }
-
- @Override
- public String toString() {
- final String familyStr = NetlinkConstants.stringForAddressFamily(mSdiagFamily);
- final String protocolStr = NetlinkConstants.stringForAddressFamily(mSdiagProtocol);
-
- return "StructInetDiagReqV2{ "
- + "sdiag_family{" + familyStr + "}, "
- + "sdiag_protocol{" + protocolStr + "}, "
- + "idiag_ext{" + mIdiagExt + ")}, "
- + "pad{" + mPad + "}, "
- + "idiag_states{" + Integer.toHexString(mState) + "}, "
- + ((mId != null) ? mId.toString() : "inet_diag_sockid=null")
- + "}";
- }
-}
diff --git a/services/net/java/android/net/netlink/StructInetDiagSockId.java b/services/net/java/android/net/netlink/StructInetDiagSockId.java
deleted file mode 100644
index 2e9fa25..0000000
--- a/services/net/java/android/net/netlink/StructInetDiagSockId.java
+++ /dev/null
@@ -1,86 +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 android.net.netlink;
-
-import static java.nio.ByteOrder.BIG_ENDIAN;
-
-import java.net.Inet4Address;
-import java.net.InetSocketAddress;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-
-/**
- * struct inet_diag_req_v2
- *
- * see <linux_src>/include/uapi/linux/inet_diag.h
- *
- * struct inet_diag_sockid {
- * __be16 idiag_sport;
- * __be16 idiag_dport;
- * __be32 idiag_src[4];
- * __be32 idiag_dst[4];
- * __u32 idiag_if;
- * __u32 idiag_cookie[2];
- * #define INET_DIAG_NOCOOKIE (~0U)
- * };
- *
- * @hide
- */
-public class StructInetDiagSockId {
- public static final int STRUCT_SIZE = 48;
-
- private final InetSocketAddress mLocSocketAddress;
- private final InetSocketAddress mRemSocketAddress;
- private final byte[] INET_DIAG_NOCOOKIE = new byte[]{
- (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
- (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff};
- private final byte[] IPV4_PADDING = new byte[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
-
- public StructInetDiagSockId(InetSocketAddress loc, InetSocketAddress rem) {
- mLocSocketAddress = loc;
- mRemSocketAddress = rem;
- }
-
- public void pack(ByteBuffer byteBuffer) {
- byteBuffer.order(BIG_ENDIAN);
- byteBuffer.putShort((short) mLocSocketAddress.getPort());
- byteBuffer.putShort((short) mRemSocketAddress.getPort());
- byteBuffer.put(mLocSocketAddress.getAddress().getAddress());
- if (mLocSocketAddress.getAddress() instanceof Inet4Address) {
- byteBuffer.put(IPV4_PADDING);
- }
- byteBuffer.put(mRemSocketAddress.getAddress().getAddress());
- if (mRemSocketAddress.getAddress() instanceof Inet4Address) {
- byteBuffer.put(IPV4_PADDING);
- }
- byteBuffer.order(ByteOrder.nativeOrder());
- byteBuffer.putInt(0);
- byteBuffer.put(INET_DIAG_NOCOOKIE);
- }
-
- @Override
- public String toString() {
- return "StructInetDiagSockId{ "
- + "idiag_sport{" + mLocSocketAddress.getPort() + "}, "
- + "idiag_dport{" + mRemSocketAddress.getPort() + "}, "
- + "idiag_src{" + mLocSocketAddress.getAddress().getHostAddress() + "}, "
- + "idiag_dst{" + mRemSocketAddress.getAddress().getHostAddress() + "}, "
- + "idiag_if{" + 0 + "} "
- + "idiag_cookie{INET_DIAG_NOCOOKIE}"
- + "}";
- }
-}
diff --git a/services/net/java/android/net/netlink/StructNdMsg.java b/services/net/java/android/net/netlink/StructNdMsg.java
deleted file mode 100644
index e34ec39..0000000
--- a/services/net/java/android/net/netlink/StructNdMsg.java
+++ /dev/null
@@ -1,166 +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 android.net.netlink;
-
-import android.net.netlink.NetlinkConstants;
-import android.system.OsConstants;
-import java.nio.ByteBuffer;
-
-
-/**
- * struct ndmsg
- *
- * see: <linux_src>/include/uapi/linux/neighbour.h
- *
- * @hide
- */
-public class StructNdMsg {
- // Already aligned.
- public static final int STRUCT_SIZE = 12;
-
- // Neighbor Cache Entry States
- public static final short NUD_NONE = 0x00;
- public static final short NUD_INCOMPLETE = 0x01;
- public static final short NUD_REACHABLE = 0x02;
- public static final short NUD_STALE = 0x04;
- public static final short NUD_DELAY = 0x08;
- public static final short NUD_PROBE = 0x10;
- public static final short NUD_FAILED = 0x20;
- public static final short NUD_NOARP = 0x40;
- public static final short NUD_PERMANENT = 0x80;
-
- public static String stringForNudState(short nudState) {
- switch (nudState) {
- case NUD_NONE: return "NUD_NONE";
- case NUD_INCOMPLETE: return "NUD_INCOMPLETE";
- case NUD_REACHABLE: return "NUD_REACHABLE";
- case NUD_STALE: return "NUD_STALE";
- case NUD_DELAY: return "NUD_DELAY";
- case NUD_PROBE: return "NUD_PROBE";
- case NUD_FAILED: return "NUD_FAILED";
- case NUD_NOARP: return "NUD_NOARP";
- case NUD_PERMANENT: return "NUD_PERMANENT";
- default:
- return "unknown NUD state: " + String.valueOf(nudState);
- }
- }
-
- public static boolean isNudStateConnected(short nudState) {
- return ((nudState & (NUD_PERMANENT|NUD_NOARP|NUD_REACHABLE)) != 0);
- }
-
- public static boolean isNudStateValid(short nudState) {
- return (isNudStateConnected(nudState) ||
- ((nudState & (NUD_PROBE|NUD_STALE|NUD_DELAY)) != 0));
- }
-
- // Neighbor Cache Entry Flags
- public static byte NTF_USE = (byte) 0x01;
- public static byte NTF_SELF = (byte) 0x02;
- public static byte NTF_MASTER = (byte) 0x04;
- public static byte NTF_PROXY = (byte) 0x08;
- public static byte NTF_ROUTER = (byte) 0x80;
-
- public static String stringForNudFlags(byte flags) {
- final StringBuilder sb = new StringBuilder();
- if ((flags & NTF_USE) != 0) {
- sb.append("NTF_USE");
- }
- if ((flags & NTF_SELF) != 0) {
- if (sb.length() > 0) { sb.append("|"); }
- sb.append("NTF_SELF");
- }
- if ((flags & NTF_MASTER) != 0) {
- if (sb.length() > 0) { sb.append("|"); }
- sb.append("NTF_MASTER");
- }
- if ((flags & NTF_PROXY) != 0) {
- if (sb.length() > 0) { sb.append("|");
- }
- sb.append("NTF_PROXY"); }
- if ((flags & NTF_ROUTER) != 0) {
- if (sb.length() > 0) { sb.append("|"); }
- sb.append("NTF_ROUTER");
- }
- return sb.toString();
- }
-
- private static boolean hasAvailableSpace(ByteBuffer byteBuffer) {
- return byteBuffer != null && byteBuffer.remaining() >= STRUCT_SIZE;
- }
-
- public static StructNdMsg parse(ByteBuffer byteBuffer) {
- if (!hasAvailableSpace(byteBuffer)) { return null; }
-
- // The ByteOrder must have already been set by the caller. In most
- // cases ByteOrder.nativeOrder() is correct, with the possible
- // exception of usage within unittests.
- final StructNdMsg struct = new StructNdMsg();
- struct.ndm_family = byteBuffer.get();
- final byte pad1 = byteBuffer.get();
- final short pad2 = byteBuffer.getShort();
- struct.ndm_ifindex = byteBuffer.getInt();
- struct.ndm_state = byteBuffer.getShort();
- struct.ndm_flags = byteBuffer.get();
- struct.ndm_type = byteBuffer.get();
- return struct;
- }
-
- public byte ndm_family;
- public int ndm_ifindex;
- public short ndm_state;
- public byte ndm_flags;
- public byte ndm_type;
-
- public StructNdMsg() {
- ndm_family = (byte) OsConstants.AF_UNSPEC;
- }
-
- public void pack(ByteBuffer byteBuffer) {
- // The ByteOrder must have already been set by the caller. In most
- // cases ByteOrder.nativeOrder() is correct, with the exception
- // of usage within unittests.
- byteBuffer.put(ndm_family);
- byteBuffer.put((byte) 0); // pad1
- byteBuffer.putShort((short) 0); // pad2
- byteBuffer.putInt(ndm_ifindex);
- byteBuffer.putShort(ndm_state);
- byteBuffer.put(ndm_flags);
- byteBuffer.put(ndm_type);
- }
-
- public boolean nudConnected() {
- return isNudStateConnected(ndm_state);
- }
-
- public boolean nudValid() {
- return isNudStateValid(ndm_state);
- }
-
- @Override
- public String toString() {
- final String stateStr = "" + ndm_state + " (" + stringForNudState(ndm_state) + ")";
- final String flagsStr = "" + ndm_flags + " (" + stringForNudFlags(ndm_flags) + ")";
- return "StructNdMsg{ "
- + "family{" + NetlinkConstants.stringForAddressFamily((int) ndm_family) + "}, "
- + "ifindex{" + ndm_ifindex + "}, "
- + "state{" + stateStr + "}, "
- + "flags{" + flagsStr + "}, "
- + "type{" + ndm_type + "} "
- + "}";
- }
-}
diff --git a/services/net/java/android/net/netlink/StructNdaCacheInfo.java b/services/net/java/android/net/netlink/StructNdaCacheInfo.java
deleted file mode 100644
index 16cf563..0000000
--- a/services/net/java/android/net/netlink/StructNdaCacheInfo.java
+++ /dev/null
@@ -1,117 +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 android.net.netlink;
-
-import android.system.Os;
-import android.system.OsConstants;
-
-import java.nio.ByteBuffer;
-
-
-/**
- * struct nda_cacheinfo
- *
- * see: <linux_src>/include/uapi/linux/neighbour.h
- *
- * @hide
- */
-public class StructNdaCacheInfo {
- // Already aligned.
- public static final int STRUCT_SIZE = 16;
-
- private static boolean hasAvailableSpace(ByteBuffer byteBuffer) {
- return byteBuffer != null && byteBuffer.remaining() >= STRUCT_SIZE;
- }
-
- public static StructNdaCacheInfo parse(ByteBuffer byteBuffer) {
- if (!hasAvailableSpace(byteBuffer)) { return null; }
-
- // The ByteOrder must have already been set by the caller. In most
- // cases ByteOrder.nativeOrder() is correct, with the possible
- // exception of usage within unittests.
- final StructNdaCacheInfo struct = new StructNdaCacheInfo();
- struct.ndm_used = byteBuffer.getInt();
- struct.ndm_confirmed = byteBuffer.getInt();
- struct.ndm_updated = byteBuffer.getInt();
- struct.ndm_refcnt = byteBuffer.getInt();
- return struct;
- }
-
- // TODO: investigate whether this can change during device runtime and
- // decide what (if anything) should be done about that.
- private static final long CLOCK_TICKS_PER_SECOND = Os.sysconf(OsConstants._SC_CLK_TCK);
-
- private static long ticksToMilliSeconds(int intClockTicks) {
- final long longClockTicks = (long) intClockTicks & 0xffffffff;
- return (longClockTicks * 1000) / CLOCK_TICKS_PER_SECOND;
- }
-
- /**
- * Explanatory notes, for reference.
- *
- * Before being returned to user space, the neighbor entry times are
- * converted to clock_t's like so:
- *
- * ndm_used = jiffies_to_clock_t(now - neigh->used);
- * ndm_confirmed = jiffies_to_clock_t(now - neigh->confirmed);
- * ndm_updated = jiffies_to_clock_t(now - neigh->updated);
- *
- * meaning that these values are expressed as "clock ticks ago". To
- * convert these clock ticks to seconds divide by sysconf(_SC_CLK_TCK).
- * When _SC_CLK_TCK is 100, for example, the ndm_* times are expressed
- * in centiseconds.
- *
- * These values are unsigned, but fortunately being expressed as "some
- * clock ticks ago", these values are typically very small (and
- * 2^31 centiseconds = 248 days).
- *
- * By observation, it appears that:
- * ndm_used: the last time ARP/ND took place for this neighbor
- * ndm_confirmed: the last time ARP/ND succeeded for this neighbor OR
- * higher layer confirmation (TCP or MSG_CONFIRM)
- * was received
- * ndm_updated: the time when the current NUD state was entered
- */
- public int ndm_used;
- public int ndm_confirmed;
- public int ndm_updated;
- public int ndm_refcnt;
-
- public StructNdaCacheInfo() {}
-
- public long lastUsed() {
- return ticksToMilliSeconds(ndm_used);
- }
-
- public long lastConfirmed() {
- return ticksToMilliSeconds(ndm_confirmed);
- }
-
- public long lastUpdated() {
- return ticksToMilliSeconds(ndm_updated);
- }
-
- @Override
- public String toString() {
- return "NdaCacheInfo{ "
- + "ndm_used{" + lastUsed() + "}, "
- + "ndm_confirmed{" + lastConfirmed() + "}, "
- + "ndm_updated{" + lastUpdated() + "}, "
- + "ndm_refcnt{" + ndm_refcnt + "} "
- + "}";
- }
-}
diff --git a/services/net/java/android/net/netlink/StructNfGenMsg.java b/services/net/java/android/net/netlink/StructNfGenMsg.java
deleted file mode 100644
index 8155977..0000000
--- a/services/net/java/android/net/netlink/StructNfGenMsg.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * 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.
- */
-
-package android.net.netlink;
-
-import java.nio.ByteBuffer;
-
-
-/**
- * struct nfgenmsg
- *
- * see <linux_src>/include/uapi/linux/netfilter/nfnetlink.h
- *
- * @hide
- */
-public class StructNfGenMsg {
- public static final int STRUCT_SIZE = 2 + Short.BYTES;
-
- public static final int NFNETLINK_V0 = 0;
-
- final public byte nfgen_family;
- final public byte version;
- final public short res_id; // N.B.: this is big endian in the kernel
-
- public StructNfGenMsg(byte family) {
- nfgen_family = family;
- version = (byte) NFNETLINK_V0;
- res_id = (short) 0;
- }
-
- public void pack(ByteBuffer byteBuffer) {
- byteBuffer.put(nfgen_family);
- byteBuffer.put(version);
- byteBuffer.putShort(res_id);
- }
-}
diff --git a/services/net/java/android/net/netlink/StructNlAttr.java b/services/net/java/android/net/netlink/StructNlAttr.java
deleted file mode 100644
index 28a4e88..0000000
--- a/services/net/java/android/net/netlink/StructNlAttr.java
+++ /dev/null
@@ -1,210 +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 android.net.netlink;
-
-import android.net.netlink.NetlinkConstants;
-
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-import java.nio.ByteOrder;
-import java.nio.ByteBuffer;
-
-
-/**
- * struct nlattr
- *
- * see: <linux_src>/include/uapi/linux/netlink.h
- *
- * @hide
- */
-public class StructNlAttr {
- // Already aligned.
- public static final int NLA_HEADERLEN = 4;
- public static final int NLA_F_NESTED = (1 << 15);
-
- public static short makeNestedType(short type) {
- return (short) (type | NLA_F_NESTED);
- }
-
- // Return a (length, type) object only, without consuming any bytes in
- // |byteBuffer| and without copying or interpreting any value bytes.
- // This is used for scanning over a packed set of struct nlattr's,
- // looking for instances of a particular type.
- public static StructNlAttr peek(ByteBuffer byteBuffer) {
- if (byteBuffer == null || byteBuffer.remaining() < NLA_HEADERLEN) {
- return null;
- }
- final int baseOffset = byteBuffer.position();
-
- // Assume the byte order of the buffer is the expected byte order of the value.
- final StructNlAttr struct = new StructNlAttr(byteBuffer.order());
- // The byte order of nla_len and nla_type is always native.
- final ByteOrder originalOrder = byteBuffer.order();
- byteBuffer.order(ByteOrder.nativeOrder());
- try {
- struct.nla_len = byteBuffer.getShort();
- struct.nla_type = byteBuffer.getShort();
- } finally {
- byteBuffer.order(originalOrder);
- }
-
- byteBuffer.position(baseOffset);
- if (struct.nla_len < NLA_HEADERLEN) {
- // Malformed.
- return null;
- }
- return struct;
- }
-
- public static StructNlAttr parse(ByteBuffer byteBuffer) {
- final StructNlAttr struct = peek(byteBuffer);
- if (struct == null || byteBuffer.remaining() < struct.getAlignedLength()) {
- return null;
- }
-
- final int baseOffset = byteBuffer.position();
- byteBuffer.position(baseOffset + NLA_HEADERLEN);
-
- int valueLen = ((int) struct.nla_len) & 0xffff;
- valueLen -= NLA_HEADERLEN;
- if (valueLen > 0) {
- struct.nla_value = new byte[valueLen];
- byteBuffer.get(struct.nla_value, 0, valueLen);
- byteBuffer.position(baseOffset + struct.getAlignedLength());
- }
- return struct;
- }
-
- public short nla_len = (short) NLA_HEADERLEN;
- public short nla_type;
- public byte[] nla_value;
-
- // The byte order used to read/write the value member. Netlink length and
- // type members are always read/written in native order.
- private ByteOrder mByteOrder = ByteOrder.nativeOrder();
-
- public StructNlAttr() {}
-
- public StructNlAttr(ByteOrder byteOrder) {
- mByteOrder = byteOrder;
- }
-
- public StructNlAttr(short type, byte value) {
- nla_type = type;
- setValue(new byte[1]);
- nla_value[0] = value;
- }
-
- public StructNlAttr(short type, short value) {
- this(type, value, ByteOrder.nativeOrder());
- }
-
- public StructNlAttr(short type, short value, ByteOrder order) {
- this(order);
- nla_type = type;
- setValue(new byte[Short.BYTES]);
- getValueAsByteBuffer().putShort(value);
- }
-
- public StructNlAttr(short type, int value) {
- this(type, value, ByteOrder.nativeOrder());
- }
-
- public StructNlAttr(short type, int value, ByteOrder order) {
- this(order);
- nla_type = type;
- setValue(new byte[Integer.BYTES]);
- getValueAsByteBuffer().putInt(value);
- }
-
- public StructNlAttr(short type, InetAddress ip) {
- nla_type = type;
- setValue(ip.getAddress());
- }
-
- public StructNlAttr(short type, StructNlAttr... nested) {
- this();
- nla_type = makeNestedType(type);
-
- int payloadLength = 0;
- for (StructNlAttr nla : nested) payloadLength += nla.getAlignedLength();
- setValue(new byte[payloadLength]);
-
- final ByteBuffer buf = getValueAsByteBuffer();
- for (StructNlAttr nla : nested) {
- nla.pack(buf);
- }
- }
-
- public int getAlignedLength() {
- return NetlinkConstants.alignedLengthOf(nla_len);
- }
-
- public ByteBuffer getValueAsByteBuffer() {
- if (nla_value == null) { return null; }
- final ByteBuffer byteBuffer = ByteBuffer.wrap(nla_value);
- byteBuffer.order(mByteOrder);
- return byteBuffer;
- }
-
- public int getValueAsInt(int defaultValue) {
- final ByteBuffer byteBuffer = getValueAsByteBuffer();
- if (byteBuffer == null || byteBuffer.remaining() != Integer.BYTES) {
- return defaultValue;
- }
- return getValueAsByteBuffer().getInt();
- }
-
- public InetAddress getValueAsInetAddress() {
- if (nla_value == null) { return null; }
-
- try {
- return InetAddress.getByAddress(nla_value);
- } catch (UnknownHostException ignored) {
- return null;
- }
- }
-
- public void pack(ByteBuffer byteBuffer) {
- final ByteOrder originalOrder = byteBuffer.order();
- final int originalPosition = byteBuffer.position();
-
- byteBuffer.order(ByteOrder.nativeOrder());
- try {
- byteBuffer.putShort(nla_len);
- byteBuffer.putShort(nla_type);
- if (nla_value != null) byteBuffer.put(nla_value);
- } finally {
- byteBuffer.order(originalOrder);
- }
- byteBuffer.position(originalPosition + getAlignedLength());
- }
-
- private void setValue(byte[] value) {
- nla_value = value;
- nla_len = (short) (NLA_HEADERLEN + ((nla_value != null) ? nla_value.length : 0));
- }
-
- @Override
- public String toString() {
- return "StructNlAttr{ "
- + "nla_len{" + nla_len + "}, "
- + "nla_type{" + nla_type + "}, "
- + "nla_value{" + NetlinkConstants.hexify(nla_value) + "}, "
- + "}";
- }
-}
diff --git a/services/net/java/android/net/netlink/StructNlMsgErr.java b/services/net/java/android/net/netlink/StructNlMsgErr.java
deleted file mode 100644
index 6fcc6e69d..0000000
--- a/services/net/java/android/net/netlink/StructNlMsgErr.java
+++ /dev/null
@@ -1,71 +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 android.net.netlink;
-
-import android.net.netlink.NetlinkConstants;
-import android.net.netlink.StructNlMsgHdr;
-
-import java.nio.ByteBuffer;
-
-
-/**
- * struct nlmsgerr
- *
- * see <linux_src>/include/uapi/linux/netlink.h
- *
- * @hide
- */
-public class StructNlMsgErr {
- public static final int STRUCT_SIZE = Integer.BYTES + StructNlMsgHdr.STRUCT_SIZE;
-
- public static boolean hasAvailableSpace(ByteBuffer byteBuffer) {
- return byteBuffer != null && byteBuffer.remaining() >= STRUCT_SIZE;
- }
-
- public static StructNlMsgErr parse(ByteBuffer byteBuffer) {
- if (!hasAvailableSpace(byteBuffer)) { return null; }
-
- // The ByteOrder must have already been set by the caller. In most
- // cases ByteOrder.nativeOrder() is correct, with the exception
- // of usage within unittests.
- final StructNlMsgErr struct = new StructNlMsgErr();
- struct.error = byteBuffer.getInt();
- struct.msg = StructNlMsgHdr.parse(byteBuffer);
- return struct;
- }
-
- public int error;
- public StructNlMsgHdr msg;
-
- public void pack(ByteBuffer byteBuffer) {
- // The ByteOrder must have already been set by the caller. In most
- // cases ByteOrder.nativeOrder() is correct, with the possible
- // exception of usage within unittests.
- byteBuffer.putInt(error);
- if (msg != null) {
- msg.pack(byteBuffer);
- }
- }
-
- @Override
- public String toString() {
- return "StructNlMsgErr{ "
- + "error{" + error + "}, "
- + "msg{" + (msg == null ? "" : msg.toString()) + "} "
- + "}";
- }
-}
diff --git a/services/net/java/android/net/netlink/StructNlMsgHdr.java b/services/net/java/android/net/netlink/StructNlMsgHdr.java
deleted file mode 100644
index 98ab5e7..0000000
--- a/services/net/java/android/net/netlink/StructNlMsgHdr.java
+++ /dev/null
@@ -1,140 +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 android.net.netlink;
-
-import android.net.netlink.NetlinkConstants;
-import java.nio.ByteBuffer;
-
-
-/**
- * struct nlmsghdr
- *
- * see <linux_src>/include/uapi/linux/netlink.h
- *
- * @hide
- */
-public class StructNlMsgHdr {
- // Already aligned.
- public static final int STRUCT_SIZE = 16;
-
- public static final short NLM_F_REQUEST = 0x0001;
- public static final short NLM_F_MULTI = 0x0002;
- public static final short NLM_F_ACK = 0x0004;
- public static final short NLM_F_ECHO = 0x0008;
- // Flags for a GET request.
- public static final short NLM_F_ROOT = 0x0100;
- public static final short NLM_F_MATCH = 0x0200;
- public static final short NLM_F_DUMP = NLM_F_ROOT|NLM_F_MATCH;
- // Flags for a NEW request.
- public static final short NLM_F_REPLACE = 0x100;
- public static final short NLM_F_EXCL = 0x200;
- public static final short NLM_F_CREATE = 0x400;
- public static final short NLM_F_APPEND = 0x800;
-
-
- public static String stringForNlMsgFlags(short flags) {
- final StringBuilder sb = new StringBuilder();
- if ((flags & NLM_F_REQUEST) != 0) {
- sb.append("NLM_F_REQUEST");
- }
- if ((flags & NLM_F_MULTI) != 0) {
- if (sb.length() > 0) { sb.append("|"); }
- sb.append("NLM_F_MULTI");
- }
- if ((flags & NLM_F_ACK) != 0) {
- if (sb.length() > 0) { sb.append("|"); }
- sb.append("NLM_F_ACK");
- }
- if ((flags & NLM_F_ECHO) != 0) {
- if (sb.length() > 0) { sb.append("|"); }
- sb.append("NLM_F_ECHO");
- }
- if ((flags & NLM_F_ROOT) != 0) {
- if (sb.length() > 0) { sb.append("|"); }
- sb.append("NLM_F_ROOT");
- }
- if ((flags & NLM_F_MATCH) != 0) {
- if (sb.length() > 0) { sb.append("|"); }
- sb.append("NLM_F_MATCH");
- }
- return sb.toString();
- }
-
- public static boolean hasAvailableSpace(ByteBuffer byteBuffer) {
- return byteBuffer != null && byteBuffer.remaining() >= STRUCT_SIZE;
- }
-
- public static StructNlMsgHdr parse(ByteBuffer byteBuffer) {
- if (!hasAvailableSpace(byteBuffer)) { return null; }
-
- // The ByteOrder must have already been set by the caller. In most
- // cases ByteOrder.nativeOrder() is correct, with the exception
- // of usage within unittests.
- final StructNlMsgHdr struct = new StructNlMsgHdr();
- struct.nlmsg_len = byteBuffer.getInt();
- struct.nlmsg_type = byteBuffer.getShort();
- struct.nlmsg_flags = byteBuffer.getShort();
- struct.nlmsg_seq = byteBuffer.getInt();
- struct.nlmsg_pid = byteBuffer.getInt();
-
- if (struct.nlmsg_len < STRUCT_SIZE) {
- // Malformed.
- return null;
- }
- return struct;
- }
-
- public int nlmsg_len;
- public short nlmsg_type;
- public short nlmsg_flags;
- public int nlmsg_seq;
- public int nlmsg_pid;
-
- public StructNlMsgHdr() {
- nlmsg_len = 0;
- nlmsg_type = 0;
- nlmsg_flags = 0;
- nlmsg_seq = 0;
- nlmsg_pid = 0;
- }
-
- public void pack(ByteBuffer byteBuffer) {
- // The ByteOrder must have already been set by the caller. In most
- // cases ByteOrder.nativeOrder() is correct, with the possible
- // exception of usage within unittests.
- byteBuffer.putInt(nlmsg_len);
- byteBuffer.putShort(nlmsg_type);
- byteBuffer.putShort(nlmsg_flags);
- byteBuffer.putInt(nlmsg_seq);
- byteBuffer.putInt(nlmsg_pid);
- }
-
- @Override
- public String toString() {
- final String typeStr = "" + nlmsg_type
- + "(" + NetlinkConstants.stringForNlMsgType(nlmsg_type) + ")";
- final String flagsStr = "" + nlmsg_flags
- + "(" + stringForNlMsgFlags(nlmsg_flags) + ")";
- return "StructNlMsgHdr{ "
- + "nlmsg_len{" + nlmsg_len + "}, "
- + "nlmsg_type{" + typeStr + "}, "
- + "nlmsg_flags{" + flagsStr + ")}, "
- + "nlmsg_seq{" + nlmsg_seq + "}, "
- + "nlmsg_pid{" + nlmsg_pid + "} "
- + "}";
- }
-}
diff --git a/services/net/java/android/net/shared/InitialConfiguration.java b/services/net/java/android/net/shared/InitialConfiguration.java
deleted file mode 100644
index 007c8ca9..0000000
--- a/services/net/java/android/net/shared/InitialConfiguration.java
+++ /dev/null
@@ -1,240 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.shared;
-
-import static android.net.shared.ParcelableUtil.fromParcelableArray;
-import static android.net.shared.ParcelableUtil.toParcelableArray;
-import static android.text.TextUtils.join;
-
-import android.net.InetAddresses;
-import android.net.InitialConfigurationParcelable;
-import android.net.IpPrefix;
-import android.net.LinkAddress;
-import android.net.RouteInfo;
-
-import java.net.Inet4Address;
-import java.net.InetAddress;
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-import java.util.function.Predicate;
-
-/** @hide */
-public class InitialConfiguration {
- public final Set<LinkAddress> ipAddresses = new HashSet<>();
- public final Set<IpPrefix> directlyConnectedRoutes = new HashSet<>();
- public final Set<InetAddress> dnsServers = new HashSet<>();
-
- private static final int RFC6177_MIN_PREFIX_LENGTH = 48;
- private static final int RFC7421_PREFIX_LENGTH = 64;
-
- public static final InetAddress INET6_ANY = InetAddresses.parseNumericAddress("::");
-
- /**
- * Create a InitialConfiguration that is a copy of the specified configuration.
- */
- public static InitialConfiguration copy(InitialConfiguration config) {
- if (config == null) {
- return null;
- }
- InitialConfiguration configCopy = new InitialConfiguration();
- configCopy.ipAddresses.addAll(config.ipAddresses);
- configCopy.directlyConnectedRoutes.addAll(config.directlyConnectedRoutes);
- configCopy.dnsServers.addAll(config.dnsServers);
- return configCopy;
- }
-
- @Override
- public String toString() {
- return String.format(
- "InitialConfiguration(IPs: {%s}, prefixes: {%s}, DNS: {%s})",
- join(", ", ipAddresses), join(", ", directlyConnectedRoutes),
- join(", ", dnsServers));
- }
-
- /**
- * Tests whether the contents of this IpConfiguration represent a valid configuration.
- */
- public boolean isValid() {
- if (ipAddresses.isEmpty()) {
- return false;
- }
-
- // For every IP address, there must be at least one prefix containing that address.
- for (LinkAddress addr : ipAddresses) {
- if (!any(directlyConnectedRoutes, (p) -> p.contains(addr.getAddress()))) {
- return false;
- }
- }
- // For every dns server, there must be at least one prefix containing that address.
- for (InetAddress addr : dnsServers) {
- if (!any(directlyConnectedRoutes, (p) -> p.contains(addr))) {
- return false;
- }
- }
- // All IPv6 LinkAddresses have an RFC7421-suitable prefix length
- // (read: compliant with RFC4291#section2.5.4).
- if (any(ipAddresses, not(InitialConfiguration::isPrefixLengthCompliant))) {
- return false;
- }
- // If directlyConnectedRoutes contains an IPv6 default route
- // then ipAddresses MUST contain at least one non-ULA GUA.
- if (any(directlyConnectedRoutes, InitialConfiguration::isIPv6DefaultRoute)
- && all(ipAddresses, not(InitialConfiguration::isIPv6GUA))) {
- return false;
- }
- // The prefix length of routes in directlyConnectedRoutes be within reasonable
- // bounds for IPv6: /48-/64 just as we’d accept in RIOs.
- if (any(directlyConnectedRoutes, not(InitialConfiguration::isPrefixLengthCompliant))) {
- return false;
- }
- // There no more than one IPv4 address
- if (ipAddresses.stream().filter(InitialConfiguration::isIPv4).count() > 1) {
- return false;
- }
-
- return true;
- }
-
- /**
- * @return true if the given list of addressess and routes satisfies provisioning for this
- * InitialConfiguration. LinkAddresses and RouteInfo objects are not compared with equality
- * because addresses and routes seen by Netlink will contain additional fields like flags,
- * interfaces, and so on. If this InitialConfiguration has no IP address specified, the
- * provisioning check always fails.
- *
- * If the given list of routes is null, only addresses are taken into considerations.
- */
- public boolean isProvisionedBy(List<LinkAddress> addresses, List<RouteInfo> routes) {
- if (ipAddresses.isEmpty()) {
- return false;
- }
-
- for (LinkAddress addr : ipAddresses) {
- if (!any(addresses, (addrSeen) -> addr.isSameAddressAs(addrSeen))) {
- return false;
- }
- }
-
- if (routes != null) {
- for (IpPrefix prefix : directlyConnectedRoutes) {
- if (!any(routes, (routeSeen) -> isDirectlyConnectedRoute(routeSeen, prefix))) {
- return false;
- }
- }
- }
-
- return true;
- }
-
- /**
- * Convert this configuration to a {@link InitialConfigurationParcelable}.
- */
- public InitialConfigurationParcelable toStableParcelable() {
- final InitialConfigurationParcelable p = new InitialConfigurationParcelable();
- p.ipAddresses = ipAddresses.toArray(new LinkAddress[0]);
- p.directlyConnectedRoutes = directlyConnectedRoutes.toArray(new IpPrefix[0]);
- p.dnsServers = toParcelableArray(
- dnsServers, IpConfigurationParcelableUtil::parcelAddress, String.class);
- return p;
- }
-
- /**
- * Create an instance of {@link InitialConfiguration} based on the contents of the specified
- * {@link InitialConfigurationParcelable}.
- */
- public static InitialConfiguration fromStableParcelable(InitialConfigurationParcelable p) {
- if (p == null) return null;
- final InitialConfiguration config = new InitialConfiguration();
- config.ipAddresses.addAll(Arrays.asList(p.ipAddresses));
- config.directlyConnectedRoutes.addAll(Arrays.asList(p.directlyConnectedRoutes));
- config.dnsServers.addAll(
- fromParcelableArray(p.dnsServers, IpConfigurationParcelableUtil::unparcelAddress));
- return config;
- }
-
- @Override
- public boolean equals(Object obj) {
- if (!(obj instanceof InitialConfiguration)) return false;
- final InitialConfiguration other = (InitialConfiguration) obj;
- return ipAddresses.equals(other.ipAddresses)
- && directlyConnectedRoutes.equals(other.directlyConnectedRoutes)
- && dnsServers.equals(other.dnsServers);
- }
-
- private static boolean isDirectlyConnectedRoute(RouteInfo route, IpPrefix prefix) {
- return !route.hasGateway() && prefix.equals(route.getDestination());
- }
-
- private static boolean isPrefixLengthCompliant(LinkAddress addr) {
- return isIPv4(addr) || isCompliantIPv6PrefixLength(addr.getPrefixLength());
- }
-
- private static boolean isPrefixLengthCompliant(IpPrefix prefix) {
- return isIPv4(prefix) || isCompliantIPv6PrefixLength(prefix.getPrefixLength());
- }
-
- private static boolean isCompliantIPv6PrefixLength(int prefixLength) {
- return (RFC6177_MIN_PREFIX_LENGTH <= prefixLength)
- && (prefixLength <= RFC7421_PREFIX_LENGTH);
- }
-
- private static boolean isIPv4(IpPrefix prefix) {
- return prefix.getAddress() instanceof Inet4Address;
- }
-
- private static boolean isIPv4(LinkAddress addr) {
- return addr.getAddress() instanceof Inet4Address;
- }
-
- private static boolean isIPv6DefaultRoute(IpPrefix prefix) {
- return prefix.getAddress().equals(INET6_ANY);
- }
-
- private static boolean isIPv6GUA(LinkAddress addr) {
- return addr.isIpv6() && addr.isGlobalPreferred();
- }
-
- // TODO: extract out into CollectionUtils.
-
- /**
- * Indicate whether any element of the specified iterable verifies the specified predicate.
- */
- public static <T> boolean any(Iterable<T> coll, Predicate<T> fn) {
- for (T t : coll) {
- if (fn.test(t)) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Indicate whether all elements of the specified iterable verifies the specified predicate.
- */
- public static <T> boolean all(Iterable<T> coll, Predicate<T> fn) {
- return !any(coll, not(fn));
- }
-
- /**
- * Create a predicate that returns the opposite value of the specified predicate.
- */
- public static <T> Predicate<T> not(Predicate<T> fn) {
- return (t) -> !fn.test(t);
- }
-}
diff --git a/services/net/java/android/net/shared/IpConfigurationParcelableUtil.java b/services/net/java/android/net/shared/IpConfigurationParcelableUtil.java
deleted file mode 100644
index 172dc24..0000000
--- a/services/net/java/android/net/shared/IpConfigurationParcelableUtil.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.shared;
-
-import android.annotation.Nullable;
-import android.net.DhcpResults;
-import android.net.DhcpResultsParcelable;
-import android.net.InetAddresses;
-
-import java.net.Inet4Address;
-import java.net.InetAddress;
-
-/**
- * Collection of utility methods to convert to and from stable AIDL parcelables for IpClient
- * configuration classes.
- * @hide
- */
-public final class IpConfigurationParcelableUtil {
- /**
- * Convert DhcpResults to a DhcpResultsParcelable.
- */
- public static DhcpResultsParcelable toStableParcelable(@Nullable DhcpResults results) {
- if (results == null) return null;
- final DhcpResultsParcelable p = new DhcpResultsParcelable();
- p.baseConfiguration = results.toStaticIpConfiguration();
- p.leaseDuration = results.leaseDuration;
- p.mtu = results.mtu;
- p.serverAddress = parcelAddress(results.serverAddress);
- p.vendorInfo = results.vendorInfo;
- p.serverHostName = results.serverHostName;
- return p;
- }
-
- /**
- * Convert a DhcpResultsParcelable to DhcpResults.
- */
- public static DhcpResults fromStableParcelable(@Nullable DhcpResultsParcelable p) {
- if (p == null) return null;
- final DhcpResults results = new DhcpResults(p.baseConfiguration);
- results.leaseDuration = p.leaseDuration;
- results.mtu = p.mtu;
- results.serverAddress = (Inet4Address) unparcelAddress(p.serverAddress);
- results.vendorInfo = p.vendorInfo;
- results.serverHostName = p.serverHostName;
- return results;
- }
-
- /**
- * Convert InetAddress to String.
- * TODO: have an InetAddressParcelable
- */
- public static String parcelAddress(@Nullable InetAddress addr) {
- if (addr == null) return null;
- return addr.getHostAddress();
- }
-
- /**
- * Convert String to InetAddress.
- * TODO: have an InetAddressParcelable
- */
- public static InetAddress unparcelAddress(@Nullable String addr) {
- if (addr == null) return null;
- return InetAddresses.parseNumericAddress(addr);
- }
-}
diff --git a/services/net/java/android/net/shared/LinkPropertiesParcelableUtil.java b/services/net/java/android/net/shared/LinkPropertiesParcelableUtil.java
deleted file mode 100644
index 1729da6..0000000
--- a/services/net/java/android/net/shared/LinkPropertiesParcelableUtil.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.shared;
-
-import android.annotation.Nullable;
-import android.net.LinkProperties;
-import android.net.ProxyInfo;
-
-/**
- * Collection of utility methods to convert to and from stable AIDL parcelables for LinkProperties
- * and its attributes.
- * @hide
- */
-public final class LinkPropertiesParcelableUtil {
- // Temporary methods to facilitate migrating clients away from LinkPropertiesParcelable
- // TODO: remove the following methods after migrating clients.
-
- /**
- * @deprecated conversion to stable parcelable is no longer necessary.
- */
- @Deprecated
- public static LinkProperties toStableParcelable(@Nullable LinkProperties lp) {
- return lp;
- }
-
- /**
- * @deprecated conversion to stable parcelable is no longer necessary.
- */
- @Deprecated
- public static ProxyInfo toStableParcelable(@Nullable ProxyInfo info) {
- return info;
- }
-}
diff --git a/services/net/java/android/net/shared/NetworkMonitorUtils.java b/services/net/java/android/net/shared/NetworkMonitorUtils.java
deleted file mode 100644
index 46e9c73..0000000
--- a/services/net/java/android/net/shared/NetworkMonitorUtils.java
+++ /dev/null
@@ -1,65 +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 android.net.shared;
-
-import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
-import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED;
-import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN;
-import static android.net.NetworkCapabilities.NET_CAPABILITY_TRUSTED;
-
-import android.net.NetworkCapabilities;
-
-/** @hide */
-public class NetworkMonitorUtils {
-
- // Network conditions broadcast constants
- public static final String ACTION_NETWORK_CONDITIONS_MEASURED =
- "android.net.conn.NETWORK_CONDITIONS_MEASURED";
- public static final String EXTRA_CONNECTIVITY_TYPE = "extra_connectivity_type";
- public static final String EXTRA_NETWORK_TYPE = "extra_network_type";
- public static final String EXTRA_RESPONSE_RECEIVED = "extra_response_received";
- public static final String EXTRA_IS_CAPTIVE_PORTAL = "extra_is_captive_portal";
- public static final String EXTRA_CELL_ID = "extra_cellid";
- public static final String EXTRA_SSID = "extra_ssid";
- public static final String EXTRA_BSSID = "extra_bssid";
- /** real time since boot */
- public static final String EXTRA_REQUEST_TIMESTAMP_MS = "extra_request_timestamp_ms";
- public static final String EXTRA_RESPONSE_TIMESTAMP_MS = "extra_response_timestamp_ms";
- public static final String PERMISSION_ACCESS_NETWORK_CONDITIONS =
- "android.permission.ACCESS_NETWORK_CONDITIONS";
-
- /**
- * Return whether validation is required for private DNS in strict mode.
- * @param nc Network capabilities of the network to test.
- */
- public static boolean isPrivateDnsValidationRequired(NetworkCapabilities nc) {
- // TODO: Consider requiring validation for DUN networks.
- return nc != null
- && nc.hasCapability(NET_CAPABILITY_INTERNET)
- && nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)
- && nc.hasCapability(NET_CAPABILITY_TRUSTED);
- }
-
- /**
- * Return whether validation is required for a network.
- * @param nc Network capabilities of the network to test.
- */
- public static boolean isValidationRequired(NetworkCapabilities nc) {
- // TODO: Consider requiring validation for DUN networks.
- return isPrivateDnsValidationRequired(nc) && nc.hasCapability(NET_CAPABILITY_NOT_VPN);
- }
-}
diff --git a/services/net/java/android/net/shared/ParcelableUtil.java b/services/net/java/android/net/shared/ParcelableUtil.java
deleted file mode 100644
index 3f40300..0000000
--- a/services/net/java/android/net/shared/ParcelableUtil.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.shared;
-
-import android.annotation.NonNull;
-
-import java.lang.reflect.Array;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.function.Function;
-
-/**
- * Utility methods to help convert to/from stable parcelables.
- * @hide
- */
-public final class ParcelableUtil {
- // Below methods could be implemented easily with streams, but streams are frowned upon in
- // frameworks code.
-
- /**
- * Convert a list of BaseType items to an array of ParcelableType items using the specified
- * converter function.
- */
- public static <ParcelableType, BaseType> ParcelableType[] toParcelableArray(
- @NonNull Collection<BaseType> base,
- @NonNull Function<BaseType, ParcelableType> conv,
- @NonNull Class<ParcelableType> parcelClass) {
- final ParcelableType[] out = (ParcelableType[]) Array.newInstance(parcelClass, base.size());
- int i = 0;
- for (BaseType b : base) {
- out[i] = conv.apply(b);
- i++;
- }
- return out;
- }
-
- /**
- * Convert an array of ParcelableType items to a list of BaseType items using the specified
- * converter function.
- */
- public static <ParcelableType, BaseType> ArrayList<BaseType> fromParcelableArray(
- @NonNull ParcelableType[] parceled, @NonNull Function<ParcelableType, BaseType> conv) {
- final ArrayList<BaseType> out = new ArrayList<>(parceled.length);
- for (ParcelableType t : parceled) {
- out.add(conv.apply(t));
- }
- return out;
- }
-}
diff --git a/services/net/java/android/net/shared/PrivateDnsConfig.java b/services/net/java/android/net/shared/PrivateDnsConfig.java
deleted file mode 100644
index c7dc530..0000000
--- a/services/net/java/android/net/shared/PrivateDnsConfig.java
+++ /dev/null
@@ -1,90 +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 android.net.shared;
-
-import static android.net.shared.ParcelableUtil.fromParcelableArray;
-import static android.net.shared.ParcelableUtil.toParcelableArray;
-
-import android.net.PrivateDnsConfigParcel;
-import android.text.TextUtils;
-
-import java.net.InetAddress;
-import java.util.Arrays;
-
-/** @hide */
-public class PrivateDnsConfig {
- public final boolean useTls;
- public final String hostname;
- public final InetAddress[] ips;
-
- public PrivateDnsConfig() {
- this(false);
- }
-
- public PrivateDnsConfig(boolean useTls) {
- this.useTls = useTls;
- this.hostname = "";
- this.ips = new InetAddress[0];
- }
-
- public PrivateDnsConfig(String hostname, InetAddress[] ips) {
- this.useTls = !TextUtils.isEmpty(hostname);
- this.hostname = useTls ? hostname : "";
- this.ips = (ips != null) ? ips : new InetAddress[0];
- }
-
- public PrivateDnsConfig(PrivateDnsConfig cfg) {
- useTls = cfg.useTls;
- hostname = cfg.hostname;
- ips = cfg.ips;
- }
-
- /**
- * Indicates whether this is a strict mode private DNS configuration.
- */
- public boolean inStrictMode() {
- return useTls && !TextUtils.isEmpty(hostname);
- }
-
- @Override
- public String toString() {
- return PrivateDnsConfig.class.getSimpleName()
- + "{" + useTls + ":" + hostname + "/" + Arrays.toString(ips) + "}";
- }
-
- /**
- * Create a stable AIDL-compatible parcel from the current instance.
- */
- public PrivateDnsConfigParcel toParcel() {
- final PrivateDnsConfigParcel parcel = new PrivateDnsConfigParcel();
- parcel.hostname = hostname;
- parcel.ips = toParcelableArray(
- Arrays.asList(ips), IpConfigurationParcelableUtil::parcelAddress, String.class);
-
- return parcel;
- }
-
- /**
- * Build a configuration from a stable AIDL-compatible parcel.
- */
- public static PrivateDnsConfig fromParcel(PrivateDnsConfigParcel parcel) {
- InetAddress[] ips = new InetAddress[parcel.ips.length];
- ips = fromParcelableArray(parcel.ips, IpConfigurationParcelableUtil::unparcelAddress)
- .toArray(ips);
- return new PrivateDnsConfig(parcel.hostname, ips);
- }
-}
diff --git a/services/net/java/android/net/shared/ProvisioningConfiguration.java b/services/net/java/android/net/shared/ProvisioningConfiguration.java
deleted file mode 100644
index 6f9c294..0000000
--- a/services/net/java/android/net/shared/ProvisioningConfiguration.java
+++ /dev/null
@@ -1,312 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.shared;
-
-import android.annotation.Nullable;
-import android.net.INetd;
-import android.net.Network;
-import android.net.ProvisioningConfigurationParcelable;
-import android.net.StaticIpConfiguration;
-import android.net.apf.ApfCapabilities;
-import android.net.ip.IIpClient;
-
-import java.util.Objects;
-import java.util.StringJoiner;
-
-/**
- * This class encapsulates parameters to be passed to
- * IpClient#startProvisioning(). A defensive copy is made by IpClient
- * and the values specified herein are in force until IpClient#stop()
- * is called.
- *
- * Example use:
- *
- * final ProvisioningConfiguration config =
- * new ProvisioningConfiguration.Builder()
- * .withPreDhcpAction()
- * .withProvisioningTimeoutMs(36 * 1000)
- * .build();
- * mIpClient.startProvisioning(config.toStableParcelable());
- * ...
- * mIpClient.stop();
- *
- * The specified provisioning configuration will only be active until
- * IIpClient#stop() is called. Future calls to IIpClient#startProvisioning()
- * must specify the configuration again.
- * @hide
- */
-public class ProvisioningConfiguration {
- // TODO: Delete this default timeout once those callers that care are
- // fixed to pass in their preferred timeout.
- //
- // We pick 36 seconds so we can send DHCP requests at
- //
- // t=0, t=2, t=6, t=14, t=30
- //
- // allowing for 10% jitter.
- private static final int DEFAULT_TIMEOUT_MS = 36 * 1000;
-
- /**
- * Builder to create a {@link ProvisioningConfiguration}.
- */
- public static class Builder {
- protected ProvisioningConfiguration mConfig = new ProvisioningConfiguration();
-
- /**
- * Specify that the configuration should not enable IPv4. It is enabled by default.
- */
- public Builder withoutIPv4() {
- mConfig.mEnableIPv4 = false;
- return this;
- }
-
- /**
- * Specify that the configuration should not enable IPv6. It is enabled by default.
- */
- public Builder withoutIPv6() {
- mConfig.mEnableIPv6 = false;
- return this;
- }
-
- /**
- * Specify that the configuration should not use a MultinetworkPolicyTracker. It is used
- * by default.
- */
- public Builder withoutMultinetworkPolicyTracker() {
- mConfig.mUsingMultinetworkPolicyTracker = false;
- return this;
- }
-
- /**
- * Specify that the configuration should not use a IpReachabilityMonitor. It is used by
- * default.
- */
- public Builder withoutIpReachabilityMonitor() {
- mConfig.mUsingIpReachabilityMonitor = false;
- return this;
- }
-
- /**
- * Identical to {@link #withPreDhcpAction(int)}, using a default timeout.
- * @see #withPreDhcpAction(int)
- */
- public Builder withPreDhcpAction() {
- mConfig.mRequestedPreDhcpActionMs = DEFAULT_TIMEOUT_MS;
- return this;
- }
-
- /**
- * Specify that {@link IpClientCallbacks#onPreDhcpAction()} should be called. Clients must
- * call {@link IIpClient#completedPreDhcpAction()} when the callback called. This behavior
- * is disabled by default.
- * @param dhcpActionTimeoutMs Timeout for clients to call completedPreDhcpAction().
- */
- public Builder withPreDhcpAction(int dhcpActionTimeoutMs) {
- mConfig.mRequestedPreDhcpActionMs = dhcpActionTimeoutMs;
- return this;
- }
-
- /**
- * Specify the initial provisioning configuration.
- */
- public Builder withInitialConfiguration(InitialConfiguration initialConfig) {
- mConfig.mInitialConfig = initialConfig;
- return this;
- }
-
- /**
- * Specify a static configuration for provisioning.
- */
- public Builder withStaticConfiguration(StaticIpConfiguration staticConfig) {
- mConfig.mStaticIpConfig = staticConfig;
- return this;
- }
-
- /**
- * Specify ApfCapabilities.
- */
- public Builder withApfCapabilities(ApfCapabilities apfCapabilities) {
- mConfig.mApfCapabilities = apfCapabilities;
- return this;
- }
-
- /**
- * Specify the timeout to use for provisioning.
- */
- public Builder withProvisioningTimeoutMs(int timeoutMs) {
- mConfig.mProvisioningTimeoutMs = timeoutMs;
- return this;
- }
-
- /**
- * Specify that IPv6 address generation should use a random MAC address.
- */
- public Builder withRandomMacAddress() {
- mConfig.mIPv6AddrGenMode = INetd.IPV6_ADDR_GEN_MODE_EUI64;
- return this;
- }
-
- /**
- * Specify that IPv6 address generation should use a stable MAC address.
- */
- public Builder withStableMacAddress() {
- mConfig.mIPv6AddrGenMode = INetd.IPV6_ADDR_GEN_MODE_STABLE_PRIVACY;
- return this;
- }
-
- /**
- * Specify the network to use for provisioning.
- */
- public Builder withNetwork(Network network) {
- mConfig.mNetwork = network;
- return this;
- }
-
- /**
- * Specify the display name that the IpClient should use.
- */
- public Builder withDisplayName(String displayName) {
- mConfig.mDisplayName = displayName;
- return this;
- }
-
- /**
- * Build the configuration using previously specified parameters.
- */
- public ProvisioningConfiguration build() {
- return new ProvisioningConfiguration(mConfig);
- }
- }
-
- public boolean mEnableIPv4 = true;
- public boolean mEnableIPv6 = true;
- public boolean mUsingMultinetworkPolicyTracker = true;
- public boolean mUsingIpReachabilityMonitor = true;
- public int mRequestedPreDhcpActionMs;
- public InitialConfiguration mInitialConfig;
- public StaticIpConfiguration mStaticIpConfig;
- public ApfCapabilities mApfCapabilities;
- public int mProvisioningTimeoutMs = DEFAULT_TIMEOUT_MS;
- public int mIPv6AddrGenMode = INetd.IPV6_ADDR_GEN_MODE_STABLE_PRIVACY;
- public Network mNetwork = null;
- public String mDisplayName = null;
-
- public ProvisioningConfiguration() {} // used by Builder
-
- public ProvisioningConfiguration(ProvisioningConfiguration other) {
- mEnableIPv4 = other.mEnableIPv4;
- mEnableIPv6 = other.mEnableIPv6;
- mUsingMultinetworkPolicyTracker = other.mUsingMultinetworkPolicyTracker;
- mUsingIpReachabilityMonitor = other.mUsingIpReachabilityMonitor;
- mRequestedPreDhcpActionMs = other.mRequestedPreDhcpActionMs;
- mInitialConfig = InitialConfiguration.copy(other.mInitialConfig);
- mStaticIpConfig = other.mStaticIpConfig == null
- ? null
- : new StaticIpConfiguration(other.mStaticIpConfig);
- mApfCapabilities = other.mApfCapabilities;
- mProvisioningTimeoutMs = other.mProvisioningTimeoutMs;
- mIPv6AddrGenMode = other.mIPv6AddrGenMode;
- mNetwork = other.mNetwork;
- mDisplayName = other.mDisplayName;
- }
-
- /**
- * Create a ProvisioningConfigurationParcelable from this ProvisioningConfiguration.
- */
- public ProvisioningConfigurationParcelable toStableParcelable() {
- final ProvisioningConfigurationParcelable p = new ProvisioningConfigurationParcelable();
- p.enableIPv4 = mEnableIPv4;
- p.enableIPv6 = mEnableIPv6;
- p.usingMultinetworkPolicyTracker = mUsingMultinetworkPolicyTracker;
- p.usingIpReachabilityMonitor = mUsingIpReachabilityMonitor;
- p.requestedPreDhcpActionMs = mRequestedPreDhcpActionMs;
- p.initialConfig = mInitialConfig == null ? null : mInitialConfig.toStableParcelable();
- p.staticIpConfig = mStaticIpConfig == null
- ? null
- : new StaticIpConfiguration(mStaticIpConfig);
- p.apfCapabilities = mApfCapabilities; // ApfCapabilities is immutable
- p.provisioningTimeoutMs = mProvisioningTimeoutMs;
- p.ipv6AddrGenMode = mIPv6AddrGenMode;
- p.network = mNetwork;
- p.displayName = mDisplayName;
- return p;
- }
-
- /**
- * Create a ProvisioningConfiguration from a ProvisioningConfigurationParcelable.
- */
- public static ProvisioningConfiguration fromStableParcelable(
- @Nullable ProvisioningConfigurationParcelable p) {
- if (p == null) return null;
- final ProvisioningConfiguration config = new ProvisioningConfiguration();
- config.mEnableIPv4 = p.enableIPv4;
- config.mEnableIPv6 = p.enableIPv6;
- config.mUsingMultinetworkPolicyTracker = p.usingMultinetworkPolicyTracker;
- config.mUsingIpReachabilityMonitor = p.usingIpReachabilityMonitor;
- config.mRequestedPreDhcpActionMs = p.requestedPreDhcpActionMs;
- config.mInitialConfig = InitialConfiguration.fromStableParcelable(p.initialConfig);
- config.mStaticIpConfig = p.staticIpConfig == null
- ? null
- : new StaticIpConfiguration(p.staticIpConfig);
- config.mApfCapabilities = p.apfCapabilities; // ApfCapabilities is immutable
- config.mProvisioningTimeoutMs = p.provisioningTimeoutMs;
- config.mIPv6AddrGenMode = p.ipv6AddrGenMode;
- config.mNetwork = p.network;
- config.mDisplayName = p.displayName;
- return config;
- }
-
- @Override
- public String toString() {
- return new StringJoiner(", ", getClass().getSimpleName() + "{", "}")
- .add("mEnableIPv4: " + mEnableIPv4)
- .add("mEnableIPv6: " + mEnableIPv6)
- .add("mUsingMultinetworkPolicyTracker: " + mUsingMultinetworkPolicyTracker)
- .add("mUsingIpReachabilityMonitor: " + mUsingIpReachabilityMonitor)
- .add("mRequestedPreDhcpActionMs: " + mRequestedPreDhcpActionMs)
- .add("mInitialConfig: " + mInitialConfig)
- .add("mStaticIpConfig: " + mStaticIpConfig)
- .add("mApfCapabilities: " + mApfCapabilities)
- .add("mProvisioningTimeoutMs: " + mProvisioningTimeoutMs)
- .add("mIPv6AddrGenMode: " + mIPv6AddrGenMode)
- .add("mNetwork: " + mNetwork)
- .add("mDisplayName: " + mDisplayName)
- .toString();
- }
-
- @Override
- public boolean equals(Object obj) {
- if (!(obj instanceof ProvisioningConfiguration)) return false;
- final ProvisioningConfiguration other = (ProvisioningConfiguration) obj;
- return mEnableIPv4 == other.mEnableIPv4
- && mEnableIPv6 == other.mEnableIPv6
- && mUsingMultinetworkPolicyTracker == other.mUsingMultinetworkPolicyTracker
- && mUsingIpReachabilityMonitor == other.mUsingIpReachabilityMonitor
- && mRequestedPreDhcpActionMs == other.mRequestedPreDhcpActionMs
- && Objects.equals(mInitialConfig, other.mInitialConfig)
- && Objects.equals(mStaticIpConfig, other.mStaticIpConfig)
- && Objects.equals(mApfCapabilities, other.mApfCapabilities)
- && mProvisioningTimeoutMs == other.mProvisioningTimeoutMs
- && mIPv6AddrGenMode == other.mIPv6AddrGenMode
- && Objects.equals(mNetwork, other.mNetwork)
- && Objects.equals(mDisplayName, other.mDisplayName);
- }
-
- public boolean isValid() {
- return (mInitialConfig == null) || mInitialConfig.isValid();
- }
-}
diff --git a/services/net/java/android/net/util/InterfaceParams.java b/services/net/java/android/net/util/InterfaceParams.java
deleted file mode 100644
index f6bb873..0000000
--- a/services/net/java/android/net/util/InterfaceParams.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * 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.
- */
-
-package android.net.util;
-
-import static com.android.internal.util.Preconditions.checkArgument;
-
-import android.net.MacAddress;
-import android.text.TextUtils;
-
-import java.net.NetworkInterface;
-import java.net.SocketException;
-
-
-/**
- * Encapsulate the interface parameters common to IpClient/IpServer components.
- *
- * Basically all java.net.NetworkInterface methods throw Exceptions. IpClient
- * and IpServer (sub)components need most or all of this information at some
- * point during their lifecycles, so pass only this simplified object around
- * which can be created once when IpClient/IpServer are told to start.
- *
- * @hide
- */
-public class InterfaceParams {
- public final String name;
- public final int index;
- public final MacAddress macAddr;
- public final int defaultMtu;
-
- // TODO: move the below to NetworkStackConstants when this class is moved to the NetworkStack.
- private static final int ETHER_MTU = 1500;
- private static final int IPV6_MIN_MTU = 1280;
-
-
- public static InterfaceParams getByName(String name) {
- final NetworkInterface netif = getNetworkInterfaceByName(name);
- if (netif == null) return null;
-
- // Not all interfaces have MAC addresses, e.g. rmnet_data0.
- final MacAddress macAddr = getMacAddress(netif);
-
- try {
- return new InterfaceParams(name, netif.getIndex(), macAddr, netif.getMTU());
- } catch (IllegalArgumentException|SocketException e) {
- return null;
- }
- }
-
- public InterfaceParams(String name, int index, MacAddress macAddr) {
- this(name, index, macAddr, ETHER_MTU);
- }
-
- public InterfaceParams(String name, int index, MacAddress macAddr, int defaultMtu) {
- checkArgument((!TextUtils.isEmpty(name)), "impossible interface name");
- checkArgument((index > 0), "invalid interface index");
- this.name = name;
- this.index = index;
- this.macAddr = (macAddr != null) ? macAddr : MacAddress.fromBytes(new byte[] {
- 0x02, 0x00, 0x00, 0x00, 0x00, 0x00 });
- this.defaultMtu = (defaultMtu > IPV6_MIN_MTU) ? defaultMtu : IPV6_MIN_MTU;
- }
-
- @Override
- public String toString() {
- return String.format("%s/%d/%s/%d", name, index, macAddr, defaultMtu);
- }
-
- private static NetworkInterface getNetworkInterfaceByName(String name) {
- try {
- return NetworkInterface.getByName(name);
- } catch (NullPointerException|SocketException e) {
- return null;
- }
- }
-
- private static MacAddress getMacAddress(NetworkInterface netif) {
- try {
- return MacAddress.fromBytes(netif.getHardwareAddress());
- } catch (IllegalArgumentException|NullPointerException|SocketException e) {
- return null;
- }
- }
-}
diff --git a/services/net/java/android/net/util/SharedLog.java b/services/net/java/android/net/util/SharedLog.java
deleted file mode 100644
index 2cdb2b0..0000000
--- a/services/net/java/android/net/util/SharedLog.java
+++ /dev/null
@@ -1,202 +0,0 @@
-/*
- * 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.
- */
-
-package android.net.util;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.text.TextUtils;
-import android.util.LocalLog;
-import android.util.Log;
-
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-import java.util.StringJoiner;
-
-
-/**
- * Class to centralize logging functionality for tethering.
- *
- * All access to class methods other than dump() must be on the same thread.
- *
- * TODO: this is a copy of SharedLog in the NetworkStack. Remove after Tethering is migrated.
- * @hide
- */
-public class SharedLog {
- private static final int DEFAULT_MAX_RECORDS = 500;
- private static final String COMPONENT_DELIMITER = ".";
-
- private enum Category {
- NONE,
- ERROR,
- MARK,
- WARN,
- };
-
- private final LocalLog mLocalLog;
- // The tag to use for output to the system log. This is not output to the
- // LocalLog because that would be redundant.
- private final String mTag;
- // The component (or subcomponent) of a system that is sharing this log.
- // This can grow in depth if components call forSubComponent() to obtain
- // their SharedLog instance. The tag is not included in the component for
- // brevity.
- private final String mComponent;
-
- public SharedLog(String tag) {
- this(DEFAULT_MAX_RECORDS, tag);
- }
-
- public SharedLog(int maxRecords, String tag) {
- this(new LocalLog(maxRecords), tag, tag);
- }
-
- private SharedLog(LocalLog localLog, String tag, String component) {
- mLocalLog = localLog;
- mTag = tag;
- mComponent = component;
- }
-
- public String getTag() {
- return mTag;
- }
-
- /**
- * Create a SharedLog based on this log with an additional component prefix on each logged line.
- */
- public SharedLog forSubComponent(String component) {
- if (!isRootLogInstance()) {
- component = mComponent + COMPONENT_DELIMITER + component;
- }
- return new SharedLog(mLocalLog, mTag, component);
- }
-
- /**
- * Dump the contents of this log.
- *
- * <p>This method may be called on any thread.
- */
- public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
- mLocalLog.readOnlyLocalLog().dump(fd, writer, args);
- }
-
- //////
- // Methods that both log an entry and emit it to the system log.
- //////
-
- /**
- * Log an error due to an exception. This does not include the exception stacktrace.
- *
- * <p>The log entry will be also added to the system log.
- * @see #e(String, Throwable)
- */
- public void e(Exception e) {
- Log.e(mTag, record(Category.ERROR, e.toString()));
- }
-
- /**
- * Log an error message.
- *
- * <p>The log entry will be also added to the system log.
- */
- public void e(String msg) {
- Log.e(mTag, record(Category.ERROR, msg));
- }
-
- /**
- * Log an error due to an exception, with the exception stacktrace if provided.
- *
- * <p>The error and exception message appear in the shared log, but the stacktrace is only
- * logged in general log output (logcat). The log entry will be also added to the system log.
- */
- public void e(@NonNull String msg, @Nullable Throwable exception) {
- if (exception == null) {
- e(msg);
- return;
- }
- Log.e(mTag, record(Category.ERROR, msg + ": " + exception.getMessage()), exception);
- }
-
- /**
- * Log an informational message.
- *
- * <p>The log entry will be also added to the system log.
- */
- public void i(String msg) {
- Log.i(mTag, record(Category.NONE, msg));
- }
-
- /**
- * Log a warning message.
- *
- * <p>The log entry will be also added to the system log.
- */
- public void w(String msg) {
- Log.w(mTag, record(Category.WARN, msg));
- }
-
- //////
- // Methods that only log an entry (and do NOT emit to the system log).
- //////
-
- /**
- * Log a general message to be only included in the in-memory log.
- *
- * <p>The log entry will *not* be added to the system log.
- */
- public void log(String msg) {
- record(Category.NONE, msg);
- }
-
- /**
- * Log a general, formatted message to be only included in the in-memory log.
- *
- * <p>The log entry will *not* be added to the system log.
- * @see String#format(String, Object...)
- */
- public void logf(String fmt, Object... args) {
- log(String.format(fmt, args));
- }
-
- /**
- * Log a message with MARK level.
- *
- * <p>The log entry will *not* be added to the system log.
- */
- public void mark(String msg) {
- record(Category.MARK, msg);
- }
-
- private String record(Category category, String msg) {
- final String entry = logLine(category, msg);
- mLocalLog.log(entry);
- return entry;
- }
-
- private String logLine(Category category, String msg) {
- final StringJoiner sj = new StringJoiner(" ");
- if (!isRootLogInstance()) sj.add("[" + mComponent + "]");
- if (category != Category.NONE) sj.add(category.toString());
- return sj.add(msg).toString();
- }
-
- // Check whether this SharedLog instance is nominally the top level in
- // a potential hierarchy of shared logs (the root of a tree),
- // or is a subcomponent within the hierarchy.
- private boolean isRootLogInstance() {
- return TextUtils.isEmpty(mComponent) || mComponent.equals(mTag);
- }
-}
diff --git a/services/print/Android.bp b/services/print/Android.bp
index 80a8c75..aad24d7 100644
--- a/services/print/Android.bp
+++ b/services/print/Android.bp
@@ -1,5 +1,12 @@
+filegroup {
+ name: "services.print-sources",
+ srcs: ["java/**/*.java"],
+ path: "java",
+ visibility: ["//frameworks/base/services"],
+}
+
java_library_static {
name: "services.print",
- srcs: ["java/**/*.java"],
+ srcs: [":services.print-sources"],
libs: ["services.core"],
}
diff --git a/services/restrictions/Android.bp b/services/restrictions/Android.bp
index 979e891..805858f 100644
--- a/services/restrictions/Android.bp
+++ b/services/restrictions/Android.bp
@@ -1,5 +1,12 @@
+filegroup {
+ name: "services.restrictions-sources",
+ srcs: ["java/**/*.java"],
+ path: "java",
+ visibility: ["//frameworks/base/services"],
+}
+
java_library_static {
name: "services.restrictions",
- srcs: ["java/**/*.java"],
+ srcs: [":services.restrictions-sources"],
libs: ["services.core"],
}
diff --git a/services/systemcaptions/Android.bp b/services/systemcaptions/Android.bp
index 4e190b6..1ce3e66 100644
--- a/services/systemcaptions/Android.bp
+++ b/services/systemcaptions/Android.bp
@@ -1,5 +1,12 @@
+filegroup {
+ name: "services.systemcaptions-sources",
+ srcs: ["java/**/*.java"],
+ path: "java",
+ visibility: ["//frameworks/base/services"],
+}
+
java_library_static {
name: "services.systemcaptions",
- srcs: ["java/**/*.java"],
+ srcs: [":services.systemcaptions-sources"],
libs: ["services.core"],
}
diff --git a/services/tests/mockingservicestests/Android.bp b/services/tests/mockingservicestests/Android.bp
index 8699669..96fedf9 100644
--- a/services/tests/mockingservicestests/Android.bp
+++ b/services/tests/mockingservicestests/Android.bp
@@ -20,7 +20,7 @@
static_libs: [
"services.core",
"services.net",
- "jobscheduler-service",
+ "service-jobscheduler",
"androidx.test.runner",
"mockito-target-extended-minus-junit4",
"platform-test-annotations",
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
index e7f6a74..6c09239 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
@@ -1027,11 +1027,28 @@
bindService(client, client2, null, 0, mock(IBinder.class));
client2.setHasForegroundServices(true, 0);
bindService(client2, app, null, 0, mock(IBinder.class));
+ ArrayList<ProcessRecord> lru = sService.mProcessList.mLruProcesses;
+ lru.clear();
+ lru.add(app);
+ lru.add(client);
+ lru.add(client2);
sService.mWakefulness = PowerManagerInternal.WAKEFULNESS_AWAKE;
- sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
+ sService.mOomAdjuster.updateOomAdjLocked(app, true, OomAdjuster.OOM_ADJ_REASON_NONE);
assertProcStates(app, PROCESS_STATE_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ,
SCHED_GROUP_DEFAULT);
+ assertProcStates(client, PROCESS_STATE_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ,
+ SCHED_GROUP_DEFAULT);
+ assertProcStates(client2, PROCESS_STATE_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ,
+ SCHED_GROUP_DEFAULT);
+
+ client2.setHasForegroundServices(false, 0);
+ sService.mWakefulness = PowerManagerInternal.WAKEFULNESS_AWAKE;
+ sService.mOomAdjuster.updateOomAdjLocked(client2, true, OomAdjuster.OOM_ADJ_REASON_NONE);
+
+ assertEquals(PROCESS_STATE_CACHED_EMPTY, client2.setProcState);
+ assertEquals(PROCESS_STATE_CACHED_EMPTY, client.setProcState);
+ assertEquals(PROCESS_STATE_CACHED_EMPTY, app.setProcState);
}
@SuppressWarnings("GuardedBy")
diff --git a/services/tests/servicestests/Android.bp b/services/tests/servicestests/Android.bp
index 52fb69e..0be5fe0 100644
--- a/services/tests/servicestests/Android.bp
+++ b/services/tests/servicestests/Android.bp
@@ -41,7 +41,7 @@
"hamcrest-library",
"servicestests-utils",
"xml-writer-device-lib",
- "jobscheduler-service",
+ "service-jobscheduler",
],
aidl: {
diff --git a/services/tests/servicestests/src/com/android/server/pm/CrossProfileAppsServiceImplTest.java b/services/tests/servicestests/src/com/android/server/pm/CrossProfileAppsServiceImplTest.java
index 839b25f..e18ff61 100644
--- a/services/tests/servicestests/src/com/android/server/pm/CrossProfileAppsServiceImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/CrossProfileAppsServiceImplTest.java
@@ -509,7 +509,7 @@
mActivityInfo = activityInfo;
when(mPackageManagerInternal.queryIntentActivities(
- any(Intent.class), anyInt(), anyInt(), anyInt()))
+ any(Intent.class), nullable(String.class), anyInt(), anyInt(), anyInt()))
.thenReturn(Collections.singletonList(resolveInfo));
}
diff --git a/services/tests/servicestests/src/com/android/server/recoverysystem/RecoverySystemServiceTest.java b/services/tests/servicestests/src/com/android/server/recoverysystem/RecoverySystemServiceTest.java
new file mode 100644
index 0000000..1f312bf
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/recoverysystem/RecoverySystemServiceTest.java
@@ -0,0 +1,197 @@
+/*
+ * 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.recoverysystem;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.os.Handler;
+import android.os.IPowerManager;
+import android.os.IRecoverySystemProgressListener;
+import android.os.Looper;
+import android.os.PowerManager;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.FileWriter;
+
+/**
+ * atest FrameworksServicesTests:RecoverySystemServiceTest
+ */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class RecoverySystemServiceTest {
+ private RecoverySystemService mRecoverySystemService;
+ private RecoverySystemServiceTestable.FakeSystemProperties mSystemProperties;
+ private RecoverySystemService.UncryptSocket mUncryptSocket;
+ private Context mContext;
+ private IPowerManager mIPowerManager;
+ private FileWriter mUncryptUpdateFileWriter;
+
+ @Before
+ public void setup() {
+ mContext = mock(Context.class);
+ mSystemProperties = new RecoverySystemServiceTestable.FakeSystemProperties();
+ mUncryptSocket = mock(RecoverySystemService.UncryptSocket.class);
+ mUncryptUpdateFileWriter = mock(FileWriter.class);
+
+ Looper looper = InstrumentationRegistry.getContext().getMainLooper();
+ mIPowerManager = mock(IPowerManager.class);
+ PowerManager powerManager = new PowerManager(mock(Context.class), mIPowerManager,
+ new Handler(looper));
+
+ mRecoverySystemService = new RecoverySystemServiceTestable(mContext, mSystemProperties,
+ powerManager, mUncryptUpdateFileWriter, mUncryptSocket);
+ }
+
+ @Test
+ public void clearBcb_success() throws Exception {
+ doNothing().when(mContext).enforceCallingOrSelfPermission(
+ eq(android.Manifest.permission.RECOVERY), any());
+ when(mUncryptSocket.getPercentageUncrypted()).thenReturn(100);
+
+ assertThat(mRecoverySystemService.clearBcb(), is(true));
+
+ assertThat(mSystemProperties.getCtlStart(), is("clear-bcb"));
+ verify(mUncryptSocket).sendAck();
+ verify(mUncryptSocket).close();
+ }
+
+ @Test
+ public void clearBcb_uncrypt_failure() throws Exception {
+ doNothing().when(mContext).enforceCallingOrSelfPermission(
+ eq(android.Manifest.permission.RECOVERY), any());
+ when(mUncryptSocket.getPercentageUncrypted()).thenReturn(0);
+
+ assertThat(mRecoverySystemService.clearBcb(), is(false));
+
+ assertThat(mSystemProperties.getCtlStart(), is("clear-bcb"));
+ verify(mUncryptSocket).sendAck();
+ verify(mUncryptSocket).close();
+ }
+
+ @Test(expected = SecurityException.class)
+ public void clearBcb_noPerm() {
+ doThrow(SecurityException.class).when(mContext).enforceCallingOrSelfPermission(
+ eq(android.Manifest.permission.RECOVERY), any());
+ mRecoverySystemService.clearBcb();
+ }
+
+ @Test
+ public void setupBcb_success() throws Exception {
+ doNothing().when(mContext).enforceCallingOrSelfPermission(
+ eq(android.Manifest.permission.RECOVERY), any());
+ when(mUncryptSocket.getPercentageUncrypted()).thenReturn(100);
+
+ assertThat(mRecoverySystemService.setupBcb("foo"), is(true));
+
+ assertThat(mSystemProperties.getCtlStart(), is("setup-bcb"));
+ verify(mUncryptSocket).sendCommand("foo");
+ verify(mUncryptSocket).sendAck();
+ verify(mUncryptSocket).close();
+ }
+
+ @Test
+ public void setupBcb_uncrypt_failure() throws Exception {
+ doNothing().when(mContext).enforceCallingOrSelfPermission(
+ eq(android.Manifest.permission.RECOVERY), any());
+ when(mUncryptSocket.getPercentageUncrypted()).thenReturn(0);
+
+ assertThat(mRecoverySystemService.setupBcb("foo"), is(false));
+
+ assertThat(mSystemProperties.getCtlStart(), is("setup-bcb"));
+ verify(mUncryptSocket).sendCommand("foo");
+ verify(mUncryptSocket).sendAck();
+ verify(mUncryptSocket).close();
+ }
+
+ @Test(expected = SecurityException.class)
+ public void setupBcb_noPerm() {
+ doThrow(SecurityException.class).when(mContext).enforceCallingOrSelfPermission(
+ eq(android.Manifest.permission.RECOVERY), any());
+ mRecoverySystemService.setupBcb("foo");
+ }
+
+ @Test
+ public void rebootRecoveryWithCommand_success() throws Exception {
+ doNothing().when(mContext).enforceCallingOrSelfPermission(
+ eq(android.Manifest.permission.RECOVERY), any());
+ when(mUncryptSocket.getPercentageUncrypted()).thenReturn(100);
+
+ mRecoverySystemService.rebootRecoveryWithCommand("foo");
+
+ assertThat(mSystemProperties.getCtlStart(), is("setup-bcb"));
+ verify(mUncryptSocket).sendCommand("foo");
+ verify(mUncryptSocket).sendAck();
+ verify(mUncryptSocket).close();
+ verify(mIPowerManager).reboot(anyBoolean(), eq("recovery"), anyBoolean());
+ }
+
+ @Test
+ public void rebootRecoveryWithCommand_failure() throws Exception {
+ doNothing().when(mContext).enforceCallingOrSelfPermission(
+ eq(android.Manifest.permission.RECOVERY), any());
+ when(mUncryptSocket.getPercentageUncrypted()).thenReturn(0);
+
+ mRecoverySystemService.rebootRecoveryWithCommand("foo");
+
+ assertThat(mSystemProperties.getCtlStart(), is("setup-bcb"));
+ verify(mUncryptSocket).sendCommand("foo");
+ verify(mUncryptSocket).sendAck();
+ verify(mUncryptSocket).close();
+ verifyNoMoreInteractions(mIPowerManager);
+ }
+
+ @Test(expected = SecurityException.class)
+ public void rebootRecoveryWithCommand_noPerm() {
+ doThrow(SecurityException.class).when(mContext).enforceCallingOrSelfPermission(
+ eq(android.Manifest.permission.RECOVERY), any());
+ mRecoverySystemService.rebootRecoveryWithCommand("foo");
+ }
+
+ @Test
+ public void uncrypt_success() throws Exception {
+ doNothing().when(mContext).enforceCallingOrSelfPermission(
+ eq(android.Manifest.permission.RECOVERY), any());
+ when(mUncryptSocket.getPercentageUncrypted()).thenReturn(0, 5, 25, 50, 90, 99, 100);
+
+ IRecoverySystemProgressListener listener = mock(IRecoverySystemProgressListener.class);
+ assertThat(mRecoverySystemService.uncrypt("foo.zip", listener), is(true));
+
+ assertThat(mSystemProperties.getCtlStart(), is("uncrypt"));
+ verify(mUncryptSocket, times(7)).getPercentageUncrypted();
+ verify(mUncryptSocket).sendAck();
+ verify(mUncryptSocket).close();
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/recoverysystem/RecoverySystemServiceTestable.java b/services/tests/servicestests/src/com/android/server/recoverysystem/RecoverySystemServiceTestable.java
new file mode 100644
index 0000000..a986b71
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/recoverysystem/RecoverySystemServiceTestable.java
@@ -0,0 +1,113 @@
+/*
+ * 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.recoverysystem;
+
+import android.content.Context;
+import android.os.PowerManager;
+
+import java.io.FileWriter;
+
+public class RecoverySystemServiceTestable extends RecoverySystemService {
+ private static class MockInjector extends RecoverySystemService.Injector {
+ private final FakeSystemProperties mSystemProperties;
+ private final PowerManager mPowerManager;
+ private final FileWriter mUncryptPackageFileWriter;
+ private final UncryptSocket mUncryptSocket;
+
+ MockInjector(Context context, FakeSystemProperties systemProperties,
+ PowerManager powerManager, FileWriter uncryptPackageFileWriter,
+ UncryptSocket uncryptSocket) {
+ super(context);
+ mSystemProperties = systemProperties;
+ mPowerManager = powerManager;
+ mUncryptPackageFileWriter = uncryptPackageFileWriter;
+ mUncryptSocket = uncryptSocket;
+ }
+
+ @Override
+ public PowerManager getPowerManager() {
+ return mPowerManager;
+ }
+
+ @Override
+ public String systemPropertiesGet(String key) {
+ return mSystemProperties.get(key);
+ }
+
+ @Override
+ public void systemPropertiesSet(String key, String value) {
+ mSystemProperties.set(key, value);
+ }
+
+ @Override
+ public boolean uncryptPackageFileDelete() {
+ return true;
+ }
+
+ @Override
+ public String getUncryptPackageFileName() {
+ return "mock-file.txt";
+ }
+
+ @Override
+ public FileWriter getUncryptPackageFileWriter() {
+ return mUncryptPackageFileWriter;
+ }
+
+ @Override
+ public UncryptSocket connectService() {
+ return mUncryptSocket;
+ }
+
+ @Override
+ public void threadSleep(long millis) {
+ }
+ }
+
+ RecoverySystemServiceTestable(Context context, FakeSystemProperties systemProperties,
+ PowerManager powerManager, FileWriter uncryptPackageFileWriter,
+ UncryptSocket uncryptSocket) {
+ super(new MockInjector(context, systemProperties, powerManager, uncryptPackageFileWriter,
+ uncryptSocket));
+ }
+
+ public static class FakeSystemProperties {
+ private String mCtlStart = null;
+
+ public String get(String key) {
+ if (RecoverySystemService.INIT_SERVICE_UNCRYPT.equals(key)
+ || RecoverySystemService.INIT_SERVICE_SETUP_BCB.equals(key)
+ || RecoverySystemService.INIT_SERVICE_CLEAR_BCB.equals(key)) {
+ return null;
+ } else {
+ throw new IllegalArgumentException("unexpected test key: " + key);
+ }
+ }
+
+ public void set(String key, String value) {
+ if ("ctl.start".equals(key)) {
+ mCtlStart = value;
+ } else {
+ throw new IllegalArgumentException("unexpected test key: " + key);
+ }
+ }
+
+ public String getCtlStart() {
+ return mCtlStart;
+ }
+ }
+}
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityDisplayTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityDisplayTests.java
index 24db657..5336811 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityDisplayTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityDisplayTests.java
@@ -134,10 +134,9 @@
public void testNotResumeHomeStackOnRemovingDisplay() {
// Create a display which supports system decoration and allows reparenting stacks to
// another display when the display is removed.
- final ActivityDisplay display = createNewActivityDisplay();
+ final ActivityDisplay display = new TestActivityDisplay.Builder(
+ mService, 1000, 1500).setSystemDecorations(true).build();
doReturn(false).when(display).shouldDestroyContentOnRemove();
- doReturn(true).when(display).supportsSystemDecorations();
- mRootActivityContainer.addChild(display, ActivityDisplay.POSITION_TOP);
// Put home stack on the display.
final ActivityStack homeStack = new StackBuilder(mRootActivityContainer)
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
index 3a6ed54..ba54859 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
@@ -1096,7 +1096,7 @@
taskTop.finishing = true;
final ActivityRecord newR = new ActivityBuilder(mService).build();
- final ActivityRecord result = mStack.resetTaskIfNeededLocked(taskTop, newR);
+ final ActivityRecord result = mStack.resetTaskIfNeeded(taskTop, newR);
assertThat(result).isEqualTo(taskTop);
}
@@ -1118,7 +1118,7 @@
r.setState(ActivityStack.ActivityState.INITIALIZING, "test");
// Ensure precondition that the activity is opaque.
assertTrue(r.occludesParent());
- mSupervisor.startSpecificActivityLocked(r, false /* andResume */,
+ mSupervisor.startSpecificActivity(r, false /* andResume */,
false /* checkConfig */);
}
mSupervisor.endDeferResume();
@@ -1145,12 +1145,12 @@
new ActivityBuilder(mService).setTask(mTask).build();
doReturn(false).when(nonTopVisibleActivity).attachedToProcess();
doReturn(true).when(nonTopVisibleActivity).shouldBeVisible(anyBoolean(), anyBoolean());
- doNothing().when(mSupervisor).startSpecificActivityLocked(any(), anyBoolean(),
+ doNothing().when(mSupervisor).startSpecificActivity(any(), anyBoolean(),
anyBoolean());
- mStack.ensureActivitiesVisibleLocked(null /* starting */, 0 /* configChanges */,
+ mStack.ensureActivitiesVisible(null /* starting */, 0 /* configChanges */,
false /* preserveWindows */);
- verify(mSupervisor).startSpecificActivityLocked(any(), eq(false) /* andResume */,
+ verify(mSupervisor).startSpecificActivity(any(), eq(false) /* andResume */,
anyBoolean());
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
index 9af90e3..ae1bb8e 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
@@ -760,8 +760,9 @@
false /* mockGetLaunchStack */);
// Create a secondary display at bottom.
- final TestActivityDisplay secondaryDisplay = createNewActivityDisplay();
- mRootActivityContainer.addChild(secondaryDisplay, POSITION_BOTTOM);
+ final TestActivityDisplay secondaryDisplay =
+ new TestActivityDisplay.Builder(mService, 1000, 1500)
+ .setPosition(POSITION_BOTTOM).build();
final ActivityStack stack = secondaryDisplay.createStack(WINDOWING_MODE_FULLSCREEN,
ACTIVITY_TYPE_STANDARD, true /* onTop */);
@@ -798,7 +799,8 @@
false /* mockGetLaunchStack */);
// Create a secondary display with an activity.
- final TestActivityDisplay secondaryDisplay = createNewActivityDisplay();
+ final TestActivityDisplay secondaryDisplay =
+ new TestActivityDisplay.Builder(mService, 1000, 1500).build();
mRootActivityContainer.addChild(secondaryDisplay, POSITION_TOP);
final ActivityRecord singleTaskActivity = createSingleTaskActivityOn(
secondaryDisplay.createStack(WINDOWING_MODE_FULLSCREEN,
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java
index e9546a2..dae1052 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java
@@ -26,7 +26,9 @@
import android.app.Activity;
import android.app.ActivityManager;
+import android.content.res.Configuration;
import android.graphics.Rect;
+import android.view.IDisplayWindowListener;
import android.view.WindowContainerTransaction;
import androidx.test.filters.MediumTest;
@@ -35,6 +37,8 @@
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.util.ArrayList;
+
/**
* Tests for the {@link ActivityTaskManagerService} class.
*
@@ -93,5 +97,56 @@
mService.applyContainerTransaction(t);
assertEquals(newBounds, stack.getBounds());
}
+
+ @Test
+ public void testDisplayWindowListener() {
+ final ArrayList<Integer> added = new ArrayList<>();
+ final ArrayList<Integer> changed = new ArrayList<>();
+ final ArrayList<Integer> removed = new ArrayList<>();
+ IDisplayWindowListener listener = new IDisplayWindowListener.Stub() {
+ @Override
+ public void onDisplayAdded(int displayId) {
+ added.add(displayId);
+ }
+
+ @Override
+ public void onDisplayConfigurationChanged(int displayId, Configuration newConfig) {
+ changed.add(displayId);
+ }
+
+ @Override
+ public void onDisplayRemoved(int displayId) {
+ removed.add(displayId);
+ }
+ };
+ mService.mWindowManager.registerDisplayWindowListener(listener);
+ // Check that existing displays call added
+ assertEquals(1, added.size());
+ assertEquals(0, changed.size());
+ assertEquals(0, removed.size());
+ added.clear();
+ // Check adding a display
+ ActivityDisplay newDisp1 = new TestActivityDisplay.Builder(mService, 600, 800).build();
+ assertEquals(1, added.size());
+ assertEquals(0, changed.size());
+ assertEquals(0, removed.size());
+ added.clear();
+ // Check that changes are reported
+ Configuration c = new Configuration(newDisp1.getRequestedOverrideConfiguration());
+ c.windowConfiguration.setBounds(new Rect(0, 0, 1000, 1300));
+ newDisp1.onRequestedOverrideConfigurationChanged(c);
+ mService.mRootActivityContainer.ensureVisibilityAndConfig(null /* starting */,
+ newDisp1.mDisplayId, false /* markFrozenIfConfigChanged */,
+ false /* deferResume */);
+ assertEquals(0, added.size());
+ assertEquals(1, changed.size());
+ assertEquals(0, removed.size());
+ changed.clear();
+ // Check that removal is reported
+ newDisp1.remove();
+ assertEquals(0, added.size());
+ assertEquals(0, changed.size());
+ assertEquals(1, removed.size());
+ }
}
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 47b39b0..7322ac3 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java
@@ -43,7 +43,6 @@
import android.os.Build;
import android.os.UserHandle;
import android.service.voice.IVoiceInteractionSession;
-import android.view.DisplayInfo;
import com.android.server.AttributeCache;
@@ -78,27 +77,9 @@
mRootActivityContainer = mService.mRootActivityContainer;
}
- /** Creates a {@link TestActivityDisplay}. */
- TestActivityDisplay createNewActivityDisplay() {
- return TestActivityDisplay.create(mSupervisor);
- }
-
- TestActivityDisplay createNewActivityDisplay(DisplayInfo info) {
- return TestActivityDisplay.create(mSupervisor, info);
- }
-
/** Creates and adds a {@link TestActivityDisplay} to supervisor at the given position. */
TestActivityDisplay addNewActivityDisplayAt(int position) {
- final TestActivityDisplay display = createNewActivityDisplay();
- mRootActivityContainer.addChild(display, position);
- return display;
- }
-
- /** Creates and adds a {@link TestActivityDisplay} to supervisor at the given position. */
- TestActivityDisplay addNewActivityDisplayAt(DisplayInfo info, int position) {
- final TestActivityDisplay display = createNewActivityDisplay(info);
- mRootActivityContainer.addChild(display, position);
- return display;
+ return new TestActivityDisplay.Builder(mService, 1000, 1500).setPosition(position).build();
}
/** Sets the default minimum task size to 1 so that tests can use small task sizes */
@@ -271,7 +252,7 @@
doReturn(true).when(activity).occludesParent();
mTask.addChild(activity);
// Make visible by default...
- activity.setHidden(false);
+ activity.setVisible(true);
}
final WindowProcessController wpc = new WindowProcessController(mService,
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java
index 6020453..d415f25 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java
@@ -62,7 +62,7 @@
final ActivityRecord translucentOpening = createActivityRecord(mDisplayContent,
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
translucentOpening.setOccludesParent(false);
- translucentOpening.setHidden(true);
+ translucentOpening.setVisible(false);
mDisplayContent.mOpeningApps.add(behind);
mDisplayContent.mOpeningApps.add(translucentOpening);
assertEquals(WindowManager.TRANSIT_TRANSLUCENT_ACTIVITY_OPEN,
@@ -90,7 +90,7 @@
final ActivityRecord translucentOpening = createActivityRecord(mDisplayContent,
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
translucentOpening.setOccludesParent(false);
- translucentOpening.setHidden(true);
+ translucentOpening.setVisible(false);
mDisplayContent.mOpeningApps.add(behind);
mDisplayContent.mOpeningApps.add(translucentOpening);
assertEquals(TRANSIT_TASK_CHANGE_WINDOWING_MODE,
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java b/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java
index 1c15096..9f3bd75 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java
@@ -252,7 +252,7 @@
@Test
@Presubmit
public void testGetOrientation() {
- mActivity.setHidden(false);
+ mActivity.setVisible(true);
mActivity.setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
@@ -261,7 +261,7 @@
assertEquals(SCREEN_ORIENTATION_LANDSCAPE, mActivity.getOrientation());
mActivity.setOccludesParent(true);
- mActivity.setHidden(true);
+ mActivity.setVisible(false);
// Can not specify orientation if app isn't visible even though it occludes parent.
assertEquals(SCREEN_ORIENTATION_UNSET, mActivity.getOrientation());
// Can specify orientation if the current orientation candidate is orientation behind.
@@ -313,7 +313,7 @@
@Test
public void testSetOrientation() {
- mActivity.setHidden(false);
+ mActivity.setVisible(true);
// Assert orientation is unspecified to start.
assertEquals(SCREEN_ORIENTATION_UNSPECIFIED, mActivity.getOrientation());
diff --git a/services/tests/wmtests/src/com/android/server/wm/HighRefreshRateBlacklistTest.java b/services/tests/wmtests/src/com/android/server/wm/HighRefreshRateBlacklistTest.java
index 5fb6f45..56cb447 100644
--- a/services/tests/wmtests/src/com/android/server/wm/HighRefreshRateBlacklistTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/HighRefreshRateBlacklistTest.java
@@ -120,6 +120,23 @@
assertFalse(mBlacklist.isBlacklisted(APP3));
}
+ @Test
+ public void testOverriddenByDeviceConfigUnrelatedFlagChanged() {
+ final Resources r = createResources(APP1);
+ final FakeDeviceConfig config = new FakeDeviceConfig();
+ mBlacklist = new HighRefreshRateBlacklist(r, config);
+ config.setBlacklist(APP2 + "," + APP3);
+ assertFalse(mBlacklist.isBlacklisted(APP1));
+ assertTrue(mBlacklist.isBlacklisted(APP2));
+ assertTrue(mBlacklist.isBlacklisted(APP3));
+
+ // Change an unrelated flag in our namespace and verify that the blacklist is intact
+ config.putPropertyAndNotify(DeviceConfig.NAMESPACE_DISPLAY_MANAGER, "someKey", "someValue");
+ assertFalse(mBlacklist.isBlacklisted(APP1));
+ assertTrue(mBlacklist.isBlacklisted(APP2));
+ assertTrue(mBlacklist.isBlacklisted(APP3));
+ }
+
private Resources createResources(String... defaultBlacklist) {
Resources r = mock(Resources.class);
when(r.getStringArray(R.array.config_highRefreshRateBlacklist))
diff --git a/services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java b/services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java
index 0908f71..79ad0c4 100644
--- a/services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java
@@ -36,7 +36,6 @@
import android.graphics.Rect;
import android.os.UserHandle;
import android.platform.test.annotations.Presubmit;
-import android.view.DisplayInfo;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.MediumTest;
@@ -103,11 +102,8 @@
deleteRecursively(mFolder);
mDisplayUniqueId = "test:" + Integer.toString(sNextUniqueId++);
- final DisplayInfo info = new DisplayInfo();
- mService.mContext.getDisplay().getDisplayInfo(info);
- info.uniqueId = mDisplayUniqueId;
- mTestDisplay = createNewActivityDisplay(info);
- mRootActivityContainer.addChild(mTestDisplay, ActivityDisplay.POSITION_TOP);
+ mTestDisplay = new TestActivityDisplay.Builder(mService, 1000, 1500)
+ .setUniqueId(mDisplayUniqueId).build();
when(mRootActivityContainer.getActivityDisplay(eq(mDisplayUniqueId)))
.thenReturn(mTestDisplay);
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 7026004..1abd366 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java
@@ -149,7 +149,7 @@
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
final ActivityRecord hiddenActivity = createActivityRecord(mDisplayContent,
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
- hiddenActivity.setHidden(true);
+ hiddenActivity.setVisible(false);
mDisplayContent.getConfiguration().windowConfiguration.setRotation(
mDisplayContent.getRotation());
mController.initialize(ACTIVITY_TYPE_HOME, new SparseBooleanArray(), homeActivity);
diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java
index d48b9d7..e67380c 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java
@@ -200,7 +200,7 @@
startRecentsActivity();
// Recents activity must be restarted, but not be resumed while running recents animation.
- verify(mRootActivityContainer.mStackSupervisor).startSpecificActivityLocked(
+ verify(mRootActivityContainer.mStackSupervisor).startSpecificActivity(
eq(recentActivity), eq(false), anyBoolean());
assertThat(recentActivity.getState()).isEqualTo(PAUSED);
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java
index 3cc781c..e2bdf87 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java
@@ -35,7 +35,6 @@
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.times;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
-import static com.android.server.wm.ActivityDisplay.POSITION_TOP;
import static com.android.server.wm.ActivityStackSupervisor.ON_TOP;
import static com.android.server.wm.RootActivityContainer.MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE;
@@ -61,7 +60,6 @@
import android.graphics.Rect;
import android.platform.test.annotations.Presubmit;
import android.util.Pair;
-import android.view.DisplayInfo;
import androidx.test.filters.MediumTest;
@@ -518,9 +516,9 @@
mockResolveSecondaryHomeActivity();
// Create secondary displays.
- final TestActivityDisplay secondDisplay = createNewActivityDisplay();
- mRootActivityContainer.addChild(secondDisplay, POSITION_TOP);
- doReturn(true).when(secondDisplay).supportsSystemDecorations();
+ final TestActivityDisplay secondDisplay =
+ new TestActivityDisplay.Builder(mService, 1000, 1500)
+ .setSystemDecorations(true).build();
doReturn(true).when(mRootActivityContainer)
.ensureVisibilityAndConfig(any(), anyInt(), anyBoolean(), anyBoolean());
@@ -585,10 +583,10 @@
@Test
public void testStartSecondaryHomeOnDisplayWithUserKeyLocked() {
// Create secondary displays.
- final TestActivityDisplay secondDisplay = createNewActivityDisplay();
- mRootActivityContainer.addChild(secondDisplay, POSITION_TOP);
+ final TestActivityDisplay secondDisplay =
+ new TestActivityDisplay.Builder(mService, 1000, 1500)
+ .setSystemDecorations(true).build();
- doReturn(true).when(secondDisplay).supportsSystemDecorations();
// Use invalid user id to let StorageManager.isUserKeyUnlocked() return false.
final int currentUser = mRootActivityContainer.mCurrentUser;
mRootActivityContainer.mCurrentUser = -1;
@@ -611,9 +609,9 @@
@Test
public void testStartSecondaryHomeOnDisplayWithoutSysDecorations() {
// Create secondary displays.
- final TestActivityDisplay secondDisplay = createNewActivityDisplay();
- mRootActivityContainer.addChild(secondDisplay, POSITION_TOP);
- doReturn(false).when(secondDisplay).supportsSystemDecorations();
+ final TestActivityDisplay secondDisplay =
+ new TestActivityDisplay.Builder(mService, 1000, 1500)
+ .setSystemDecorations(false).build();
mRootActivityContainer.startHomeOnDisplay(0 /* userId */, "testStartSecondaryHome",
secondDisplay.mDisplayId, true /* allowInstrumenting */, true /* fromHomeKey */);
@@ -834,12 +832,9 @@
@Test
public void testGetLaunchStackWithRealCallerId() {
// Create a non-system owned virtual display.
- final DisplayInfo info = new DisplayInfo();
- mSupervisor.mService.mContext.getDisplay().getDisplayInfo(info);
- info.type = TYPE_VIRTUAL;
- info.ownerUid = 100;
- final TestActivityDisplay secondaryDisplay = TestActivityDisplay.create(mSupervisor, info);
- mRootActivityContainer.addChild(secondaryDisplay, POSITION_TOP);
+ final TestActivityDisplay secondaryDisplay =
+ new TestActivityDisplay.Builder(mService, 1000, 1500)
+ .setType(TYPE_VIRTUAL).setOwnerUid(100).build();
// Create an activity with specify the original launch pid / uid.
final ActivityRecord r = new ActivityBuilder(mService).setLaunchedFromPid(200)
diff --git a/services/tests/wmtests/src/com/android/server/wm/RunningTasksTest.java b/services/tests/wmtests/src/com/android/server/wm/RunningTasksTest.java
index 15dcbf5..eba2bc8 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RunningTasksTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RunningTasksTest.java
@@ -18,7 +18,6 @@
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
-import static android.view.Display.DEFAULT_DISPLAY;
import static com.google.common.truth.Truth.assertThat;
@@ -59,13 +58,15 @@
public void testCollectTasksByLastActiveTime() {
// Create a number of stacks with tasks (of incrementing active time)
final ArrayList<ActivityDisplay> displays = new ArrayList<>();
- final ActivityDisplay display = TestActivityDisplay.create(mSupervisor, DEFAULT_DISPLAY);
+ final ActivityDisplay display =
+ new TestActivityDisplay.Builder(mService, 1000, 2500).build();
displays.add(display);
final int numStacks = 2;
for (int stackIndex = 0; stackIndex < numStacks; stackIndex++) {
final ActivityStack stack = new StackBuilder(mRootActivityContainer)
.setCreateActivity(false)
+ .setDisplay(display)
.setOnTop(false)
.build();
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
index b9e1d4b..212931b 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
@@ -290,10 +290,12 @@
public void testFixedScreenLayoutSizeBits() {
setUpApp(new TestActivityDisplay.Builder(mService, 1000, 2500).build());
final int fixedScreenLayout = Configuration.SCREENLAYOUT_LONG_NO
- | Configuration.SCREENLAYOUT_SIZE_NORMAL;
+ | Configuration.SCREENLAYOUT_SIZE_NORMAL
+ | Configuration.SCREENLAYOUT_COMPAT_NEEDED;
final int layoutMask = Configuration.SCREENLAYOUT_LONG_MASK
| Configuration.SCREENLAYOUT_SIZE_MASK
- | Configuration.SCREENLAYOUT_LAYOUTDIR_MASK;
+ | Configuration.SCREENLAYOUT_LAYOUTDIR_MASK
+ | Configuration.SCREENLAYOUT_COMPAT_NEEDED;
Configuration c = new Configuration(mTask.getRequestedOverrideConfiguration());
c.screenLayout = fixedScreenLayout | Configuration.SCREENLAYOUT_LAYOUTDIR_LTR;
mTask.onRequestedOverrideConfigurationChanged(c);
diff --git a/services/tests/wmtests/src/com/android/server/wm/SystemServiceTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/SystemServiceTestsBase.java
index d1b6f6f..7e31895 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SystemServiceTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SystemServiceTestsBase.java
@@ -40,6 +40,10 @@
mLockRule.waitForLocked(mSystemServicesTestRule::waitUntilWindowManagerHandlersIdle);
}
+ void cleanupWindowManagerHandlers() {
+ mLockRule.waitForLocked(mSystemServicesTestRule::cleanupWindowManagerHandlers);
+ }
+
boolean waitHandlerIdle(Handler handler) {
return waitHandlerIdle(handler, 0 /* timeout */);
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
index 2c34f33..d3b68e0 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
@@ -355,6 +355,8 @@
}
wm.mH.removeCallbacksAndMessages(null);
wm.mAnimationHandler.removeCallbacksAndMessages(null);
+ // This is a different handler object than the wm.mAnimationHandler above.
+ AnimationThread.getHandler().removeCallbacksAndMessages(null);
SurfaceAnimationThread.getHandler().removeCallbacksAndMessages(null);
}
@@ -367,6 +369,8 @@
wm.mH.removeMessages(WindowManagerService.H.FORCE_GC);
waitHandlerIdle(wm.mH);
waitHandlerIdle(wm.mAnimationHandler);
+ // This is a different handler object than the wm.mAnimationHandler above.
+ waitHandlerIdle(AnimationThread.getHandler());
waitHandlerIdle(SurfaceAnimationThread.getHandler());
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java
index b07a27b..c8f81f4 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java
@@ -37,7 +37,6 @@
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
import static com.android.server.policy.WindowManagerPolicy.USER_ROTATION_FREE;
import static com.android.server.wm.DisplayRotation.FIXED_TO_USER_ROTATION_ENABLED;
-import static com.android.server.wm.WindowContainer.POSITION_TOP;
import static com.google.common.truth.Truth.assertThat;
@@ -266,11 +265,8 @@
public void testFullscreenBoundsForcedOrientation() {
final Rect fullScreenBounds = new Rect(0, 0, 1920, 1080);
final Rect fullScreenBoundsPort = new Rect(0, 0, 1080, 1920);
- DisplayInfo info = new DisplayInfo();
- mService.mContext.getDisplay().getDisplayInfo(info);
- info.logicalWidth = fullScreenBounds.width();
- info.logicalHeight = fullScreenBounds.height();
- ActivityDisplay display = addNewActivityDisplayAt(info, POSITION_TOP);
+ ActivityDisplay display = new TestActivityDisplay.Builder(
+ mService, fullScreenBounds.width(), fullScreenBounds.height()).build();
assertTrue(mRootActivityContainer.getActivityDisplay(display.mDisplayId) != null);
// Fix the display orientation to landscape which is the natural rotation (0) for the test
// display.
@@ -332,11 +328,8 @@
@Test
public void testIgnoresForcedOrientationWhenParentHandles() {
final Rect fullScreenBounds = new Rect(0, 0, 1920, 1080);
- DisplayInfo info = new DisplayInfo();
- mService.mContext.getDisplay().getDisplayInfo(info);
- info.logicalWidth = fullScreenBounds.width();
- info.logicalHeight = fullScreenBounds.height();
- ActivityDisplay display = addNewActivityDisplayAt(info, POSITION_TOP);
+ ActivityDisplay display = new TestActivityDisplay.Builder(
+ mService, fullScreenBounds.width(), fullScreenBounds.height()).build();
display.getRequestedOverrideConfiguration().orientation =
Configuration.ORIENTATION_LANDSCAPE;
diff --git a/services/tests/wmtests/src/com/android/server/wm/TestActivityDisplay.java b/services/tests/wmtests/src/com/android/server/wm/TestActivityDisplay.java
index 48ec261..247cd87 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TestActivityDisplay.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TestActivityDisplay.java
@@ -17,7 +17,6 @@
package com.android.server.wm;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
-import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyBoolean;
@@ -39,36 +38,6 @@
class TestActivityDisplay extends ActivityDisplay {
private final ActivityStackSupervisor mSupervisor;
- static TestActivityDisplay create(ActivityStackSupervisor supervisor) {
- return create(supervisor, SystemServicesTestRule.sNextDisplayId++);
- }
-
- static TestActivityDisplay create(ActivityStackSupervisor supervisor, DisplayInfo info) {
- return create(supervisor, SystemServicesTestRule.sNextDisplayId++, info);
- }
-
- static TestActivityDisplay create(ActivityStackSupervisor supervisor, int displayId) {
- final DisplayInfo info = new DisplayInfo();
- supervisor.mService.mContext.getDisplay().getDisplayInfo(info);
- return create(supervisor, displayId, info);
- }
-
- static TestActivityDisplay create(ActivityStackSupervisor supervisor, int displayId,
- DisplayInfo info) {
- if (displayId == DEFAULT_DISPLAY) {
- synchronized (supervisor.mService.mGlobalLock) {
- return new TestActivityDisplay(supervisor,
- supervisor.mRootActivityContainer.mDisplayManager.getDisplay(displayId));
- }
- }
- final Display display = new Display(DisplayManagerGlobal.getInstance(), displayId,
- info, DEFAULT_DISPLAY_ADJUSTMENTS);
-
- synchronized (supervisor.mService.mGlobalLock) {
- return new TestActivityDisplay(supervisor, display);
- }
- }
-
private TestActivityDisplay(ActivityStackSupervisor supervisor, Display display) {
super(supervisor.mService.mRootActivityContainer, display);
// Normally this comes from display-properties as exposed by WM. Without that, just
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java
index cc90ca1..4d25a83 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java
@@ -18,8 +18,6 @@
import static android.view.Display.INVALID_DISPLAY;
-import static com.android.server.wm.ActivityDisplay.POSITION_TOP;
-
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
@@ -132,8 +130,6 @@
}
private TestActivityDisplay createTestActivityDisplayInContainer() {
- final TestActivityDisplay testActivityDisplay = createNewActivityDisplay();
- mRootActivityContainer.addChild(testActivityDisplay, POSITION_TOP);
- return testActivityDisplay;
+ return new TestActivityDisplay.Builder(mService, 1000, 1500).build();
}
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
index 8af47bc..eed5ef5 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
@@ -383,11 +383,11 @@
@Test
public void testCanAffectSystemUiFlags() {
final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
- app.mToken.setHidden(false);
+ app.mActivityRecord.setVisible(true);
assertTrue(app.canAffectSystemUiFlags());
- app.mToken.setHidden(true);
+ app.mActivityRecord.setVisible(false);
assertFalse(app.canAffectSystemUiFlags());
- app.mToken.setHidden(false);
+ app.mActivityRecord.setVisible(true);
app.mAttrs.alpha = 0.0f;
assertFalse(app.canAffectSystemUiFlags());
}
@@ -395,7 +395,7 @@
@Test
public void testCanAffectSystemUiFlags_disallow() {
final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
- app.mToken.setHidden(false);
+ app.mActivityRecord.setVisible(true);
assertTrue(app.canAffectSystemUiFlags());
app.getTask().setCanAffectSystemUiFlags(false);
assertFalse(app.canAffectSystemUiFlags());
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java
index 34a2369..26743c8 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java
@@ -74,7 +74,7 @@
private static void postCreateActivitySetup(ActivityRecord activity, DisplayContent dc) {
activity.onDisplayChanged(dc);
activity.setOccludesParent(true);
- activity.setHidden(false);
+ activity.setVisible(true);
activity.mVisibleRequested = true;
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
index 0da9dc4..437b84b 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
@@ -36,8 +36,6 @@
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
-import static com.android.server.wm.ActivityDisplay.POSITION_TOP;
-
import static org.mockito.Mockito.mock;
import android.content.Context;
@@ -175,7 +173,7 @@
}
// Cleaned up everything in Handler.
- mSystemServicesTestRule.cleanupWindowManagerHandlers();
+ cleanupWindowManagerHandlers();
} catch (Exception e) {
Log.e(TAG, "Failed to tear down test", e);
throw e;
@@ -343,8 +341,7 @@
/** Creates a {@link DisplayContent} and adds it to the system. */
DisplayContent createNewDisplay(DisplayInfo info) {
final ActivityDisplay display =
- TestActivityDisplay.create(mWm.mAtmService.mStackSupervisor, info);
- mWm.mAtmService.mRootActivityContainer.addChild(display, POSITION_TOP);
+ new TestActivityDisplay.Builder(mWm.mAtmService, info).build();
return display.mDisplayContent;
}
diff --git a/services/usage/Android.bp b/services/usage/Android.bp
index 1064b6e..156bf33 100644
--- a/services/usage/Android.bp
+++ b/services/usage/Android.bp
@@ -1,5 +1,12 @@
+filegroup {
+ name: "services.usage-sources",
+ srcs: ["java/**/*.java"],
+ path: "java",
+ visibility: ["//frameworks/base/services"],
+}
+
java_library_static {
name: "services.usage",
- srcs: ["java/**/*.java"],
+ srcs: [":services.usage-sources"],
libs: ["services.core"],
}
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index f9b3659..63b062e 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -347,7 +347,7 @@
Slog.i(TAG, "Attempted to unlock stopped or removed user " + userId);
return;
}
- userService.userUnlocked(System.currentTimeMillis());
+
// Process all the pending reported events
while (pendingEvents.peek() != null) {
reportEvent(pendingEvents.poll(), userId);
@@ -466,6 +466,7 @@
if (mUserUnlockedStates.get(userId)) {
try {
service.init(currentTimeMillis);
+ mUserState.put(userId, service);
} catch (Exception e) {
if (mUserManager.isUserUnlocked(userId)) {
throw e; // rethrow exception - user is unlocked
@@ -476,7 +477,6 @@
}
}
}
- mUserState.put(userId, service);
}
return service;
}
diff --git a/services/usage/java/com/android/server/usage/UserUsageStatsService.java b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
index 5783932..c6a5fcf 100644
--- a/services/usage/java/com/android/server/usage/UserUsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
@@ -165,10 +165,6 @@
}
}
- void userUnlocked(long currentTimeMillis) {
- init(currentTimeMillis);
- }
-
void userStopped() {
// Flush events to disk immediately to guarantee persistence.
persistActiveStats();
diff --git a/services/usb/Android.bp b/services/usb/Android.bp
index 20855b7..d2c973a 100644
--- a/services/usb/Android.bp
+++ b/services/usb/Android.bp
@@ -1,6 +1,13 @@
+filegroup {
+ name: "services.usb-sources",
+ srcs: ["java/**/*.java"],
+ path: "java",
+ visibility: ["//frameworks/base/services"],
+}
+
java_library_static {
name: "services.usb",
- srcs: ["java/**/*.java"],
+ srcs: [":services.usb-sources"],
libs: [
"services.core",
diff --git a/services/voiceinteraction/Android.bp b/services/voiceinteraction/Android.bp
index 390406f..85b96f34 100644
--- a/services/voiceinteraction/Android.bp
+++ b/services/voiceinteraction/Android.bp
@@ -1,5 +1,12 @@
+filegroup {
+ name: "services.voiceinteraction-sources",
+ srcs: ["java/**/*.java"],
+ path: "java",
+ visibility: ["//frameworks/base/services"],
+}
+
java_library_static {
name: "services.voiceinteraction",
- srcs: ["java/**/*.java"],
+ srcs: [":services.voiceinteraction-sources"],
libs: ["services.core"],
}
diff --git a/services/wifi/Android.bp b/services/wifi/Android.bp
index 608fc2c..8a7f73f 100644
--- a/services/wifi/Android.bp
+++ b/services/wifi/Android.bp
@@ -1,14 +1,16 @@
-// Interfaces between the core system and the wifi mainline module.
-java_library_static {
- name: "services.wifi",
+filegroup {
+ name: "services.wifi-sources",
srcs: [
"java/**/*.java",
"java/**/*.aidl",
],
- aidl: {
- local_include_dirs: ["java"]
- },
- libs: [
- "services.net",
- ],
+ path: "java",
+ visibility: ["//frameworks/base/services"],
+}
+
+// Interfaces between the core system and the wifi mainline module.
+java_library_static {
+ name: "services.wifi",
+ srcs: [":services.wifi-sources"],
+ libs: ["services.net"],
}
diff --git a/startop/iorap/Android.bp b/startop/iorap/Android.bp
index 59a80fb..993d1e1 100644
--- a/startop/iorap/Android.bp
+++ b/startop/iorap/Android.bp
@@ -12,19 +12,24 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+filegroup {
+ name: "services.startop.iorap-javasources",
+ srcs: ["src/**/*.java"],
+ path: "src",
+ visibility: ["//visibility:private"],
+}
+
+filegroup {
+ name: "services.startop.iorap-sources",
+ srcs: [
+ ":services.startop.iorap-javasources",
+ ":iorap-aidl",
+ ],
+ visibility: ["//frameworks/base/services:__subpackages__"],
+}
+
java_library_static {
name: "services.startop.iorap",
-
- aidl: {
- include_dirs: [
- "system/iorap/binder",
- ],
- },
-
+ srcs: [":services.startop.iorap-sources"],
libs: ["services.core"],
-
- srcs: [
- ":iorap-aidl",
- "**/*.java",
- ],
}
diff --git a/telephony/java/android/provider/Telephony.java b/telephony/java/android/provider/Telephony.java
index 15bb002..7ed37c4 100644
--- a/telephony/java/android/provider/Telephony.java
+++ b/telephony/java/android/provider/Telephony.java
@@ -25,6 +25,7 @@
import android.annotation.SystemApi;
import android.annotation.TestApi;
import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.ChangeId;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.ContentValues;
@@ -4033,6 +4034,16 @@
@Retention(RetentionPolicy.SOURCE)
public @interface Skip464XlatStatus {}
+ /**
+ * Compat framework change ID for the APN db read permission change.
+ *
+ * In API level 30 and beyond, accessing the APN database will require the
+ * {@link android.Manifest.permission#WRITE_APN_SETTINGS} permission. This change ID tracks
+ * apps that are affected because they don't hold this permission.
+ * @hide
+ */
+ @ChangeId
+ public static final long APN_READING_PERMISSION_CHANGE_ID = 124107808L;
}
/**
@@ -4090,9 +4101,7 @@
/**
* The subscription which received this cell broadcast message.
- * @deprecated use {@link #SLOT_INDEX} instead.
* <P>Type: INTEGER</P>
- * @hide
*/
public static final String SUB_ID = "sub_id";
@@ -4366,6 +4375,7 @@
public static final String[] QUERY_COLUMNS_FWK = {
_ID,
SLOT_INDEX,
+ SUB_ID,
GEOGRAPHICAL_SCOPE,
PLMN,
LAC,
diff --git a/telephony/java/android/telephony/CellIdentityNr.java b/telephony/java/android/telephony/CellIdentityNr.java
index 6df60ba..edc838c 100644
--- a/telephony/java/android/telephony/CellIdentityNr.java
+++ b/telephony/java/android/telephony/CellIdentityNr.java
@@ -62,6 +62,12 @@
}
/** @hide */
+ public CellIdentityNr(android.hardware.radio.V1_4.CellIdentityNr cid) {
+ this(cid.pci, cid.tac, cid.nrarfcn, cid.mcc, cid.mnc, cid.nci, cid.operatorNames.alphaLong,
+ cid.operatorNames.alphaShort);
+ }
+
+ /** @hide */
public CellIdentityNr sanitizeLocationInfo() {
return new CellIdentityNr(CellInfo.UNAVAILABLE, CellInfo.UNAVAILABLE, CellInfo.UNAVAILABLE,
mMccStr, mMncStr, CellInfo.UNAVAILABLE, mAlphaLong, mAlphaShort);
diff --git a/telephony/java/android/telephony/CellInfo.java b/telephony/java/android/telephony/CellInfo.java
index 18687d4..ae45307 100644
--- a/telephony/java/android/telephony/CellInfo.java
+++ b/telephony/java/android/telephony/CellInfo.java
@@ -374,6 +374,7 @@
case Info.hidl_discriminator.lte: return new CellInfoLte(ci, timeStamp);
case Info.hidl_discriminator.wcdma: return new CellInfoWcdma(ci, timeStamp);
case Info.hidl_discriminator.tdscdma: return new CellInfoTdscdma(ci, timeStamp);
+ case Info.hidl_discriminator.nr: return new CellInfoNr(ci, timeStamp);
default: return null;
}
}
diff --git a/telephony/java/android/telephony/CellInfoNr.java b/telephony/java/android/telephony/CellInfoNr.java
index cea8323..8b41b8b 100644
--- a/telephony/java/android/telephony/CellInfoNr.java
+++ b/telephony/java/android/telephony/CellInfoNr.java
@@ -45,6 +45,14 @@
mCellSignalStrength = other.mCellSignalStrength;
}
+ /** @hide */
+ public CellInfoNr(android.hardware.radio.V1_4.CellInfo ci, long timeStamp) {
+ super(ci, timeStamp);
+ final android.hardware.radio.V1_4.CellInfoNr cil = ci.info.nr();
+ mCellIdentity = new CellIdentityNr(cil.cellidentity);
+ mCellSignalStrength = new CellSignalStrengthNr(cil.signalStrength);
+ }
+
/**
* @return a {@link CellIdentityNr} instance.
*/
diff --git a/telephony/java/android/telephony/SmsCbMessage.java b/telephony/java/android/telephony/SmsCbMessage.java
index 737ead1..fad70d2 100644
--- a/telephony/java/android/telephony/SmsCbMessage.java
+++ b/telephony/java/android/telephony/SmsCbMessage.java
@@ -205,7 +205,9 @@
/** CMAS warning area coordinates. */
private final List<Geometry> mGeometries;
- private int mSlotIndex = 0;
+ private final int mSlotIndex;
+
+ private final int mSubId;
/**
* Create a new SmsCbMessage with the specified data.
@@ -214,11 +216,11 @@
public SmsCbMessage(int messageFormat, int geographicalScope, int serialNumber,
@NonNull SmsCbLocation location, int serviceCategory, @Nullable String language,
@Nullable String body, int priority, @Nullable SmsCbEtwsInfo etwsWarningInfo,
- @Nullable SmsCbCmasInfo cmasWarningInfo, int slotIndex) {
+ @Nullable SmsCbCmasInfo cmasWarningInfo, int slotIndex, int subId) {
this(messageFormat, geographicalScope, serialNumber, location, serviceCategory, language,
body, priority, etwsWarningInfo, cmasWarningInfo, 0 /* maximumWaitingTime */,
- null /* geometries */, System.currentTimeMillis(), slotIndex);
+ null /* geometries */, System.currentTimeMillis(), slotIndex, subId);
}
/**
@@ -226,10 +228,12 @@
* coordinates information.
*/
public SmsCbMessage(int messageFormat, int geographicalScope, int serialNumber,
- @NonNull SmsCbLocation location, int serviceCategory, @Nullable String language,
- @Nullable String body, int priority, @Nullable SmsCbEtwsInfo etwsWarningInfo,
- @Nullable SmsCbCmasInfo cmasWarningInfo, int maximumWaitTimeSec,
- @Nullable List<Geometry> geometries, long receivedTimeMillis, int slotIndex) {
+ @NonNull SmsCbLocation location, int serviceCategory,
+ @Nullable String language, @Nullable String body, int priority,
+ @Nullable SmsCbEtwsInfo etwsWarningInfo,
+ @Nullable SmsCbCmasInfo cmasWarningInfo, int maximumWaitTimeSec,
+ @Nullable List<Geometry> geometries, long receivedTimeMillis, int slotIndex,
+ int subId) {
mMessageFormat = messageFormat;
mGeographicalScope = geographicalScope;
mSerialNumber = serialNumber;
@@ -244,6 +248,7 @@
mGeometries = geometries;
mMaximumWaitTimeSec = maximumWaitTimeSec;
mSlotIndex = slotIndex;
+ mSubId = subId;
}
/**
@@ -282,6 +287,7 @@
mGeometries = geoStr != null ? CbGeoUtils.parseGeometriesFromString(geoStr) : null;
mMaximumWaitTimeSec = in.readInt();
mSlotIndex = in.readInt();
+ mSubId = in.readInt();
}
/**
@@ -317,6 +323,7 @@
mGeometries != null ? CbGeoUtils.encodeGeometriesToString(mGeometries) : null);
dest.writeInt(mMaximumWaitTimeSec);
dest.writeInt(mSlotIndex);
+ dest.writeInt(mSubId);
}
@NonNull
@@ -427,14 +434,22 @@
}
/**
- * Get the slotIndex associated with this message.
- * @return the slotIndex associated with this message
+ * Get the slot index associated with this message.
+ * @return the slot index associated with this message
*/
public int getSlotIndex() {
return mSlotIndex;
}
/**
+ * Get the subscription id associated with this message.
+ * @return the subscription id associated with this message
+ */
+ public int getSubscriptionId() {
+ return mSubId;
+ }
+
+ /**
* Get the message format ({@link #MESSAGE_FORMAT_3GPP} or {@link #MESSAGE_FORMAT_3GPP2}).
* @return an integer representing 3GPP or 3GPP2 message format
*/
@@ -536,6 +551,7 @@
public ContentValues getContentValues() {
ContentValues cv = new ContentValues(16);
cv.put(CellBroadcasts.SLOT_INDEX, mSlotIndex);
+ cv.put(CellBroadcasts.SUB_ID, mSubId);
cv.put(CellBroadcasts.GEOGRAPHICAL_SCOPE, mGeographicalScope);
if (mLocation.getPlmn() != null) {
cv.put(CellBroadcasts.PLMN, mLocation.getPlmn());
@@ -577,7 +593,6 @@
}
cv.put(CellBroadcasts.MAXIMUM_WAIT_TIME, mMaximumWaitTimeSec);
- cv.put(CellBroadcasts.SLOT_INDEX, mSlotIndex);
return cv;
}
@@ -600,6 +615,7 @@
int format = cursor.getInt(cursor.getColumnIndexOrThrow(CellBroadcasts.MESSAGE_FORMAT));
int priority = cursor.getInt(cursor.getColumnIndexOrThrow(CellBroadcasts.MESSAGE_PRIORITY));
int slotIndex = cursor.getInt(cursor.getColumnIndexOrThrow(CellBroadcasts.SLOT_INDEX));
+ int subId = cursor.getInt(cursor.getColumnIndexOrThrow(CellBroadcasts.SUB_ID));
String plmn;
int plmnColumn = cursor.getColumnIndex(CellBroadcasts.PLMN);
@@ -697,7 +713,7 @@
return new SmsCbMessage(format, geoScope, serialNum, location, category,
language, body, priority, etwsInfo, cmasInfo, maximumWaitTimeSec, geometries,
- receivedTimeMillis, slotIndex);
+ receivedTimeMillis, slotIndex, subId);
}
/**
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 1357e9c..a55d166 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -8988,7 +8988,10 @@
@Deprecated
public boolean isTtyModeSupported() {
try {
- TelecomManager telecomManager = TelecomManager.from(mContext);
+ TelecomManager telecomManager = null;
+ if (mContext != null) {
+ telecomManager = mContext.getSystemService(TelecomManager.class);
+ }
if (telecomManager != null) {
return telecomManager.isTtySupported();
}
@@ -11088,14 +11091,66 @@
}
/**
- * Broadcast intent action for Ota emergency number database installation complete.
+ * Indicates Emergency number database version is invalid.
*
* @hide
*/
- @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ @TestApi
@SystemApi
- public static final String ACTION_OTA_EMERGENCY_NUMBER_DB_INSTALLED =
- "android.telephony.action.OTA_EMERGENCY_NUMBER_DB_INSTALLED";
+ public static final int INVALID_EMERGENCY_NUMBER_DB_VERSION = -1;
+
+ /**
+ * Notify Telephony for OTA emergency number database installation complete.
+ *
+ * <p> Requires permission:
+ * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
+ *
+ * @hide
+ */
+ @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+ @SystemApi
+ public void notifyOtaEmergencyNumberDbInstalled() {
+ try {
+ ITelephony telephony = getITelephony();
+ if (telephony != null) {
+ telephony.notifyOtaEmergencyNumberDbInstalled();
+ } else {
+ throw new IllegalStateException("telephony service is null.");
+ }
+ } catch (RemoteException ex) {
+ Log.e(TAG, "notifyOtaEmergencyNumberDatabaseInstalled RemoteException", ex);
+ ex.rethrowAsRuntimeException();
+ }
+ }
+
+ /**
+ * Override the file path for testing OTA emergency number database in a file partition.
+ *
+ * @param otaFilePath The test OTA emergency number database file path;
+ * if "RESET", recover the original database file partition.
+ * Format: <root file folder>@<file path>
+ *
+ * <p> Requires permission:
+ * {@link android.Manifest.permission#READ_ACTIVE_EMERGENCY_SESSION}
+ *
+ * @hide
+ */
+ @RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION)
+ @SystemApi
+ @TestApi
+ public void updateTestOtaEmergencyNumberDbFilePath(@NonNull String otaFilePath) {
+ try {
+ ITelephony telephony = getITelephony();
+ if (telephony != null) {
+ telephony.updateTestOtaEmergencyNumberDbFilePath(otaFilePath);
+ } else {
+ throw new IllegalStateException("telephony service is null.");
+ }
+ } catch (RemoteException ex) {
+ Log.e(TAG, "notifyOtaEmergencyNumberDatabaseInstalled RemoteException", ex);
+ ex.rethrowAsRuntimeException();
+ }
+ }
/**
* Returns whether {@link TelephonyManager#ACTION_EMERGENCY_ASSISTANCE emergency assistance} is
@@ -11293,6 +11348,29 @@
return false;
}
+ /**
+ * A test API to return the emergency number db version.
+ *
+ * <p>Requires Permission:
+ * {@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE READ_PRIVILEGED_PHONE_STATE}
+ *
+ * @hide
+ */
+ @TestApi
+ @SystemApi
+ public int getEmergencyNumberDbVersion() {
+ try {
+ ITelephony telephony = getITelephony();
+ if (telephony != null) {
+ return telephony.getEmergencyNumberDbVersion(getSubId());
+ }
+ } catch (RemoteException ex) {
+ Log.e(TAG, "getEmergencyNumberDbVersion RemoteException", ex);
+ ex.rethrowAsRuntimeException();
+ }
+ return INVALID_EMERGENCY_NUMBER_DB_VERSION;
+ }
+
/** @hide */
@Retention(RetentionPolicy.SOURCE)
@IntDef(prefix = {"SET_OPPORTUNISTIC_SUB"}, value = {
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index e895bae..0ec54ec 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -2048,6 +2048,21 @@
List<String> getEmergencyNumberListTestMode();
/**
+ * A test API to return the emergency number db version.
+ */
+ int getEmergencyNumberDbVersion(int subId);
+
+ /**
+ * Notify Telephony for OTA emergency number database installation complete.
+ */
+ void notifyOtaEmergencyNumberDbInstalled();
+
+ /**
+ * Override the file partition name for testing OTA emergency number database.
+ */
+ void updateTestOtaEmergencyNumberDbFilePath(String otaFilePath);
+
+ /**
* Enable or disable a logical modem stack associated with the slotIndex.
*/
boolean enableModemForSlot(int slotIndex, boolean enable);
diff --git a/telephony/java/com/android/internal/telephony/SmsMessageBase.java b/telephony/java/com/android/internal/telephony/SmsMessageBase.java
index f0687b4..a3efb75 100644
--- a/telephony/java/com/android/internal/telephony/SmsMessageBase.java
+++ b/telephony/java/com/android/internal/telephony/SmsMessageBase.java
@@ -20,7 +20,6 @@
import android.os.Build;
import android.provider.Telephony;
import android.telephony.SmsMessage;
-import android.text.Emoji;
import com.android.internal.telephony.GsmAlphabet.TextEncodingDetails;
@@ -403,9 +402,9 @@
if (!breakIterator.isBoundary(nextPos)) {
int breakPos = breakIterator.preceding(nextPos);
while (breakPos + 4 <= nextPos
- && Emoji.isRegionalIndicatorSymbol(
+ && isRegionalIndicatorSymbol(
Character.codePointAt(msgBody, breakPos))
- && Emoji.isRegionalIndicatorSymbol(
+ && isRegionalIndicatorSymbol(
Character.codePointAt(msgBody, breakPos + 2))) {
// skip forward over flags (pairs of Regional Indicator Symbol)
breakPos += 4;
@@ -421,6 +420,11 @@
return nextPos;
}
+ private static boolean isRegionalIndicatorSymbol(int codePoint) {
+ /** Based on http://unicode.org/Public/emoji/3.0/emoji-sequences.txt */
+ return 0x1F1E6 <= codePoint && codePoint <= 0x1F1FF;
+ }
+
/**
* Calculate the TextEncodingDetails of a message encoded in Unicode.
*/
diff --git a/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java b/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java
index 6fc0228..1f7715b 100644
--- a/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java
+++ b/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java
@@ -875,9 +875,10 @@
* Parses a broadcast SMS, possibly containing a CMAS alert.
*
* @param plmn the PLMN for a broadcast SMS
- * @param subId
+ * @param slotIndex SIM slot index
+ * @param subId Subscription id
*/
- public SmsCbMessage parseBroadcastSms(String plmn, int subId) {
+ public SmsCbMessage parseBroadcastSms(String plmn, int slotIndex, int subId) {
BearerData bData = BearerData.decode(mEnvelope.bearerData, mEnvelope.serviceCategory);
if (bData == null) {
Rlog.w(LOG_TAG, "BearerData.decode() returned null");
@@ -893,7 +894,7 @@
return new SmsCbMessage(SmsCbMessage.MESSAGE_FORMAT_3GPP2,
SmsCbMessage.GEOGRAPHICAL_SCOPE_PLMN_WIDE, bData.messageId, location,
mEnvelope.serviceCategory, bData.getLanguage(), bData.userData.payloadStr,
- bData.priority, null, bData.cmasWarningInfo, subId);
+ bData.priority, null, bData.cmasWarningInfo, slotIndex, subId);
}
/**
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmSmsCbMessage.java b/telephony/java/com/android/internal/telephony/gsm/GsmSmsCbMessage.java
index d03419d..c16eafb 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmSmsCbMessage.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmSmsCbMessage.java
@@ -33,6 +33,7 @@
import android.telephony.Rlog;
import android.telephony.SmsCbLocation;
import android.telephony.SmsCbMessage;
+import android.telephony.SubscriptionManager;
import android.util.Pair;
import com.android.internal.R;
@@ -95,6 +96,14 @@
public static SmsCbMessage createSmsCbMessage(Context context, SmsCbHeader header,
SmsCbLocation location, byte[][] pdus, int slotIndex)
throws IllegalArgumentException {
+ SubscriptionManager sm = (SubscriptionManager) context.getSystemService(
+ Context.TELEPHONY_SUBSCRIPTION_SERVICE);
+ int subId = SubscriptionManager.DEFAULT_SUBSCRIPTION_ID;
+ int[] subIds = sm.getSubscriptionIds(slotIndex);
+ if (subIds != null && subIds.length > 0) {
+ subId = subIds[0];
+ }
+
long receivedTimeMillis = System.currentTimeMillis();
if (header.isEtwsPrimaryNotification()) {
// ETSI TS 23.041 ETWS Primary Notification message
@@ -105,7 +114,8 @@
header.getSerialNumber(), location, header.getServiceCategory(), null,
getEtwsPrimaryMessage(context, header.getEtwsInfo().getWarningType()),
SmsCbMessage.MESSAGE_PRIORITY_EMERGENCY, header.getEtwsInfo(),
- header.getCmasInfo(), 0, null /* geometries */, receivedTimeMillis, slotIndex);
+ header.getCmasInfo(), 0, null /* geometries */, receivedTimeMillis, slotIndex,
+ subId);
} else if (header.isUmtsFormat()) {
// UMTS format has only 1 PDU
byte[] pdu = pdus[0];
@@ -139,7 +149,7 @@
header.getGeographicalScope(), header.getSerialNumber(), location,
header.getServiceCategory(), language, body, priority,
header.getEtwsInfo(), header.getCmasInfo(), maximumWaitingTimeSec, geometries,
- receivedTimeMillis, slotIndex);
+ receivedTimeMillis, slotIndex, subId);
} else {
String language = null;
StringBuilder sb = new StringBuilder();
@@ -155,7 +165,7 @@
header.getGeographicalScope(), header.getSerialNumber(), location,
header.getServiceCategory(), language, sb.toString(), priority,
header.getEtwsInfo(), header.getCmasInfo(), 0, null /* geometries */,
- receivedTimeMillis, slotIndex);
+ receivedTimeMillis, slotIndex, subId);
}
}
diff --git a/tests/ApkVerityTest/block_device_writer/Android.bp b/tests/ApkVerityTest/block_device_writer/Android.bp
index deed3a0..e7a63e4 100644
--- a/tests/ApkVerityTest/block_device_writer/Android.bp
+++ b/tests/ApkVerityTest/block_device_writer/Android.bp
@@ -22,7 +22,13 @@
stem: "block_device_writer",
srcs: ["block_device_writer.cpp"],
- cflags: ["-Wall", "-Werror", "-Wextra", "-g"],
+ cflags: [
+ "-D_FILE_OFFSET_BITS=64",
+ "-Wall",
+ "-Werror",
+ "-Wextra",
+ "-g",
+ ],
shared_libs: ["libbase", "libutils"],
test_suites: ["general-tests"],
diff --git a/tests/BackgroundDexOptServiceIntegrationTests/AndroidManifest.xml b/tests/BackgroundDexOptServiceIntegrationTests/AndroidManifest.xml
index 7291dc7..aec9f77 100644
--- a/tests/BackgroundDexOptServiceIntegrationTests/AndroidManifest.xml
+++ b/tests/BackgroundDexOptServiceIntegrationTests/AndroidManifest.xml
@@ -28,8 +28,6 @@
<uses-permission android:name="android.permission.SET_TIME" />
<uses-permission android:name="android.permission.UPDATE_DEVICE_STATS" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
- <uses-permission android:name="android.permission.WRITE_DEVICE_CONFIG" />
- <uses-permission android:name="android.permission.READ_DEVICE_CONFIG" />
<application>
<uses-library android:name="android.test.runner" />
diff --git a/tests/BackgroundDexOptServiceIntegrationTests/src/com/android/server/pm/BackgroundDexOptServiceIntegrationTests.java b/tests/BackgroundDexOptServiceIntegrationTests/src/com/android/server/pm/BackgroundDexOptServiceIntegrationTests.java
index 4cd56c3..7d826f7 100644
--- a/tests/BackgroundDexOptServiceIntegrationTests/src/com/android/server/pm/BackgroundDexOptServiceIntegrationTests.java
+++ b/tests/BackgroundDexOptServiceIntegrationTests/src/com/android/server/pm/BackgroundDexOptServiceIntegrationTests.java
@@ -22,7 +22,6 @@
import android.os.ParcelFileDescriptor;
import android.os.SystemProperties;
import android.os.storage.StorageManager;
-import android.provider.DeviceConfig;
import android.util.Log;
import androidx.test.InstrumentationRegistry;
@@ -31,9 +30,7 @@
import org.junit.Assert;
import org.junit.Before;
import org.junit.BeforeClass;
-import org.junit.Rule;
import org.junit.Test;
-import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
@@ -55,13 +52,6 @@
* 3. Under low storage conditions and package is recently used, check
* that dexopt upgrades test app to $(getprop pm.dexopt.bg-dexopt).
*
- * When downgrade feature is on (downgrade_unused_apps_enabled flag is set to true):
- * 4 On low storage, check that the inactive packages are downgraded.
- * 5. On low storage, check that used packages are upgraded.
- * 6. On storage completely full, dexopt fails.
- * 7. Not on low storage, unused packages are upgraded.
- * 8. Low storage, unused app is downgraded. When app is used again, app is upgraded.
- *
* Each test case runs "cmd package bg-dexopt-job com.android.frameworks.bgdexopttest".
*
* The setup for these tests make sure this package has been configured to have been recently used
@@ -69,10 +59,6 @@
* recently used, it sets the time forward more than
* `getprop pm.dexopt.downgrade_after_inactive_days` days.
*
- * For some of the tests, the DeviceConfig flags inactive_app_threshold_days and
- * downgrade_unused_apps_enabled are set. These turn on/off the downgrade unused apps feature for
- * all devices and set the time threshold for unused apps.
- *
* For tests that require low storage, the phone is filled up.
*
* Run with "atest BackgroundDexOptServiceIntegrationTests".
@@ -94,14 +80,10 @@
"pm.dexopt.downgrade_after_inactive_days", 0);
// Needs to be between 1.0 and 2.0.
private static final double LOW_STORAGE_MULTIPLIER = 1.5;
- private static final int DOWNGRADE_FEATURE_PKG_INACTIVE_AFTER_DAYS = 15;
// The file used to fill up storage.
private File mBigFile;
- @Rule
- public ExpectedException mExpectedException = ExpectedException.none();
-
// Remember start time.
@BeforeClass
public static void setUpAll() {
@@ -214,27 +196,11 @@
logSpaceRemaining();
}
- private void fillUpStorageCompletely() throws IOException {
- fillUpStorage((getStorageLowBytes()));
- }
-
// Fill up storage so that device is in low storage condition.
private void fillUpToLowStorage() throws IOException {
fillUpStorage((long) (getStorageLowBytes() * LOW_STORAGE_MULTIPLIER));
}
- private void setInactivePackageThreshold(int threshold) {
- DeviceConfig.setProperty(
- DeviceConfig.NAMESPACE_PACKAGE_MANAGER_SERVICE,
- "inactive_app_threshold_days", Integer.toString(threshold), false);
- }
-
- private void enableDowngradeFeature(boolean enabled) {
- DeviceConfig.setProperty(
- DeviceConfig.NAMESPACE_PACKAGE_MANAGER_SERVICE,
- "downgrade_unused_apps_enabled", Boolean.toString(enabled), false);
- }
-
// TODO(aeubanks): figure out how to get scheduled bg-dexopt to run
private static void runBackgroundDexOpt() throws IOException {
String result = runShellCommand("cmd package bg-dexopt-job " + PACKAGE_NAME);
@@ -278,7 +244,7 @@
// Test that background dexopt under normal conditions succeeds.
@Test
- public void testBackgroundDexOpt_normalConditions_dexOptSucceeds() throws IOException {
+ public void testBackgroundDexOpt() throws IOException {
// Set filter to quicken.
compilePackageWithFilter(PACKAGE_NAME, "verify");
Assert.assertEquals("verify", getCompilerFilter(PACKAGE_NAME));
@@ -291,16 +257,17 @@
// Test that background dexopt under low storage conditions upgrades used packages.
@Test
- public void testBackgroundDexOpt_lowStorage_usedPkgsUpgraded() throws IOException {
+ public void testBackgroundDexOptDowngradeSkipRecentlyUsedPackage() throws IOException {
// Should be less than DOWNGRADE_AFTER_DAYS.
long deltaDays = DOWNGRADE_AFTER_DAYS - 1;
try {
- enableDowngradeFeature(false);
// Set time to future.
setTimeFutureDays(deltaDays);
+
// Set filter to quicken.
compilePackageWithFilter(PACKAGE_NAME, "quicken");
Assert.assertEquals("quicken", getCompilerFilter(PACKAGE_NAME));
+
// Fill up storage to trigger low storage threshold.
fillUpToLowStorage();
@@ -315,20 +282,18 @@
}
// Test that background dexopt under low storage conditions downgrades unused packages.
- // This happens if the system property pm.dexopt.downgrade_after_inactive_days is set
- // (e.g. on Android Go devices).
@Test
- public void testBackgroundDexOpt_lowStorage_unusedPkgsDowngraded()
- throws IOException {
+ public void testBackgroundDexOptDowngradeSuccessful() throws IOException {
// Should be more than DOWNGRADE_AFTER_DAYS.
long deltaDays = DOWNGRADE_AFTER_DAYS + 1;
try {
- enableDowngradeFeature(false);
// Set time to future.
setTimeFutureDays(deltaDays);
+
// Set filter to quicken.
compilePackageWithFilter(PACKAGE_NAME, "quicken");
Assert.assertEquals("quicken", getCompilerFilter(PACKAGE_NAME));
+
// Fill up storage to trigger low storage threshold.
fillUpToLowStorage();
@@ -342,134 +307,4 @@
}
}
- // Test that the background dexopt downgrades inactive packages when the downgrade feature is
- // enabled.
- @Test
- public void testBackgroundDexOpt_downgradeFeatureEnabled_lowStorage_inactivePkgsDowngraded()
- throws IOException {
- // Should be more than DOWNGRADE_FEATURE_PKG_INACTIVE_AFTER_DAYS.
- long deltaDays = DOWNGRADE_FEATURE_PKG_INACTIVE_AFTER_DAYS + 1;
- try {
- enableDowngradeFeature(true);
- setInactivePackageThreshold(DOWNGRADE_FEATURE_PKG_INACTIVE_AFTER_DAYS);
- // Set time to future.
- setTimeFutureDays(deltaDays);
- // Set filter to quicken.
- compilePackageWithFilter(PACKAGE_NAME, "quicken");
- Assert.assertEquals("quicken", getCompilerFilter(PACKAGE_NAME));
- // Fill up storage to trigger low storage threshold.
- fillUpToLowStorage();
-
- runBackgroundDexOpt();
-
- // Verify that downgrade is successful.
- Assert.assertEquals(DOWNGRADE_COMPILER_FILTER, getCompilerFilter(PACKAGE_NAME));
- } finally {
- // Reset time.
- setTimeFutureDays(-deltaDays);
- }
- }
-
- // Test that the background dexopt upgrades used packages when the downgrade feature is enabled.
- // This test doesn't fill the device storage completely, but to a multiplier of the low storage
- // threshold and this is why apps can still be optimized.
- @Test
- public void testBackgroundDexOpt_downgradeFeatureEnabled_lowStorage_usedPkgsUpgraded()
- throws IOException {
- enableDowngradeFeature(true);
- // Set filter to quicken.
- compilePackageWithFilter(PACKAGE_NAME, "quicken");
- Assert.assertEquals("quicken", getCompilerFilter(PACKAGE_NAME));
- // Fill up storage to trigger low storage threshold.
- fillUpToLowStorage();
-
- runBackgroundDexOpt();
-
- /// Verify that bg-dexopt is successful in upgrading the used packages.
- Assert.assertEquals(BG_DEXOPT_COMPILER_FILTER, getCompilerFilter(PACKAGE_NAME));
- }
-
- // Test that the background dexopt fails and doesn't change the compilation filter of used
- // packages when the downgrade feature is enabled and the storage is filled up completely.
- // The bg-dexopt shouldn't optimise nor downgrade these packages.
- @Test
- public void testBackgroundDexOpt_downgradeFeatureEnabled_fillUpStorageCompletely_dexOptFails()
- throws IOException {
- enableDowngradeFeature(true);
- String previousCompilerFilter = getCompilerFilter(PACKAGE_NAME);
-
- // Fill up storage completely, without using a multiplier for the low storage threshold.
- fillUpStorageCompletely();
-
- // When the bg dexopt runs with the storage filled up completely, it will fail.
- mExpectedException.expect(IllegalStateException.class);
- runBackgroundDexOpt();
-
- /// Verify that bg-dexopt doesn't change the compilation filter of used apps.
- Assert.assertEquals(previousCompilerFilter, getCompilerFilter(PACKAGE_NAME));
- }
-
- // Test that the background dexopt upgrades the unused packages when the downgrade feature is
- // on if the device is not low on storage.
- @Test
- public void testBackgroundDexOpt_downgradeFeatureEnabled_notLowStorage_unusedPkgsUpgraded()
- throws IOException {
- // Should be more than DOWNGRADE_FEATURE_PKG_INACTIVE_AFTER_DAYS.
- long deltaDays = DOWNGRADE_FEATURE_PKG_INACTIVE_AFTER_DAYS + 1;
- try {
- enableDowngradeFeature(true);
- setInactivePackageThreshold(DOWNGRADE_FEATURE_PKG_INACTIVE_AFTER_DAYS);
- // Set time to future.
- setTimeFutureDays(deltaDays);
- // Set filter to quicken.
- compilePackageWithFilter(PACKAGE_NAME, "quicken");
- Assert.assertEquals("quicken", getCompilerFilter(PACKAGE_NAME));
-
- runBackgroundDexOpt();
-
- // Verify that bg-dexopt is successful in upgrading the unused packages when the device
- // is not low on storage.
- Assert.assertEquals(BG_DEXOPT_COMPILER_FILTER, getCompilerFilter(PACKAGE_NAME));
- } finally {
- // Reset time.
- setTimeFutureDays(-deltaDays);
- }
- }
-
- // Test that when an unused package (which was downgraded) is used again, it's re-optimized when
- // bg-dexopt runs again.
- @Test
- public void testBackgroundDexOpt_downgradeFeatureEnabled_downgradedPkgsUpgradedAfterUse()
- throws IOException {
- // Should be more than DOWNGRADE_FEATURE_PKG_INACTIVE_AFTER_DAYS.
- long deltaDays = DOWNGRADE_FEATURE_PKG_INACTIVE_AFTER_DAYS + 1;
- try {
- enableDowngradeFeature(true);
- setInactivePackageThreshold(DOWNGRADE_FEATURE_PKG_INACTIVE_AFTER_DAYS);
- // Set time to future.
- setTimeFutureDays(deltaDays);
- // Fill up storage to trigger low storage threshold.
- fillUpToLowStorage();
- // Set filter to quicken.
- compilePackageWithFilter(PACKAGE_NAME, "quicken");
- Assert.assertEquals("quicken", getCompilerFilter(PACKAGE_NAME));
-
- runBackgroundDexOpt();
-
- // Verify that downgrade is successful.
- Assert.assertEquals(DOWNGRADE_COMPILER_FILTER, getCompilerFilter(PACKAGE_NAME));
-
- // Reset time.
- setTimeFutureDays(-deltaDays);
- deltaDays = 0;
- runBackgroundDexOpt();
-
- // Verify that bg-dexopt is successful in upgrading the unused packages that were used
- // again.
- Assert.assertEquals(BG_DEXOPT_COMPILER_FILTER, getCompilerFilter(PACKAGE_NAME));
- } finally {
- // Reset time.
- setTimeFutureDays(-deltaDays);
- }
- }
}
diff --git a/tests/JobSchedulerPerfTests/Android.bp b/tests/JobSchedulerPerfTests/Android.bp
index c51b811..2ae8c33 100644
--- a/tests/JobSchedulerPerfTests/Android.bp
+++ b/tests/JobSchedulerPerfTests/Android.bp
@@ -19,7 +19,7 @@
"androidx.test.rules",
"apct-perftests-utils",
"services",
- "jobscheduler-service",
+ "service-jobscheduler",
],
platform_apis: true,
certificate: "platform",
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 599ee56..abe6c61 100644
--- a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java
+++ b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java
@@ -1054,4 +1054,48 @@
InstallUtils.dropShellPermissionIdentity();
}
}
+
+ @Test
+ public void testEnableRollbackTimeoutFailsRollback_MultiPackage() throws Exception {
+ try {
+ InstallUtils.adoptShellPermissionIdentity(
+ Manifest.permission.INSTALL_PACKAGES,
+ Manifest.permission.DELETE_PACKAGES,
+ Manifest.permission.TEST_MANAGE_ROLLBACKS,
+ Manifest.permission.MANAGE_ROLLBACKS,
+ Manifest.permission.WRITE_DEVICE_CONFIG);
+
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ROLLBACK,
+ PROPERTY_ENABLE_ROLLBACK_TIMEOUT_MILLIS,
+ Long.toString(5000), false /* makeDefault*/);
+ RollbackManager rm = RollbackUtils.getRollbackManager();
+
+ Uninstall.packages(TestApp.A, TestApp.B);
+ Install.multi(TestApp.A1, TestApp.B1).commit();
+ waitForUnavailableRollback(TestApp.A);
+
+ // Block the 2nd session for 10s so it will not be able to enable the rollback in time.
+ rm.blockRollbackManager(TimeUnit.SECONDS.toMillis(0));
+ rm.blockRollbackManager(TimeUnit.SECONDS.toMillis(10));
+ Install.multi(TestApp.A2, TestApp.B2).setEnableRollback().commit();
+
+ assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2);
+ assertThat(InstallUtils.getInstalledVersion(TestApp.B)).isEqualTo(2);
+
+ // Give plenty of time for RollbackManager to unblock and attempt
+ // to make the rollback available before asserting that the
+ // rollback was not made available.
+ Thread.sleep(TimeUnit.SECONDS.toMillis(2));
+
+ List<RollbackInfo> available = rm.getAvailableRollbacks();
+ assertThat(getUniqueRollbackInfoForPackage(available, TestApp.A)).isNull();
+ assertThat(getUniqueRollbackInfoForPackage(available, TestApp.B)).isNull();
+ } finally {
+ //setting the timeout back to default
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ROLLBACK,
+ PROPERTY_ENABLE_ROLLBACK_TIMEOUT_MILLIS,
+ null, false /* makeDefault*/);
+ InstallUtils.dropShellPermissionIdentity();
+ }
+ }
}
diff --git a/tests/net/java/android/net/ip/InterfaceControllerTest.java b/tests/net/java/android/net/ip/InterfaceControllerTest.java
deleted file mode 100644
index 7a56b3a..0000000
--- a/tests/net/java/android/net/ip/InterfaceControllerTest.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.ip;
-
-import static org.junit.Assert.assertArrayEquals;
-import static org.junit.Assert.assertEquals;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.doNothing;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-
-import android.net.INetd;
-import android.net.InetAddresses;
-import android.net.InterfaceConfigurationParcel;
-import android.net.LinkAddress;
-import android.net.util.SharedLog;
-
-import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Captor;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-@RunWith(AndroidJUnit4.class)
-@SmallTest
-public class InterfaceControllerTest {
- private static final String TEST_IFACE = "testif";
- private static final String TEST_IPV4_ADDR = "192.168.123.28";
- private static final int TEST_PREFIXLENGTH = 31;
-
- @Mock private INetd mNetd;
- @Mock private SharedLog mLog;
- @Captor private ArgumentCaptor<InterfaceConfigurationParcel> mConfigCaptor;
-
- private InterfaceController mController;
-
- @Before
- public void setUp() throws Exception {
- MockitoAnnotations.initMocks(this);
- mController = new InterfaceController(TEST_IFACE, mNetd, mLog);
-
- doNothing().when(mNetd).interfaceSetCfg(mConfigCaptor.capture());
- }
-
- @Test
- public void testSetIPv4Address() throws Exception {
- mController.setIPv4Address(
- new LinkAddress(InetAddresses.parseNumericAddress(TEST_IPV4_ADDR),
- TEST_PREFIXLENGTH));
- verify(mNetd, times(1)).interfaceSetCfg(any());
- final InterfaceConfigurationParcel parcel = mConfigCaptor.getValue();
- assertEquals(TEST_IFACE, parcel.ifName);
- assertEquals(TEST_IPV4_ADDR, parcel.ipv4Addr);
- assertEquals(TEST_PREFIXLENGTH, parcel.prefixLength);
- assertEquals("", parcel.hwAddr);
- assertArrayEquals(new String[0], parcel.flags);
- }
-
- @Test
- public void testClearIPv4Address() throws Exception {
- mController.clearIPv4Address();
- verify(mNetd, times(1)).interfaceSetCfg(any());
- final InterfaceConfigurationParcel parcel = mConfigCaptor.getValue();
- assertEquals(TEST_IFACE, parcel.ifName);
- assertEquals("0.0.0.0", parcel.ipv4Addr);
- assertEquals(0, parcel.prefixLength);
- assertEquals("", parcel.hwAddr);
- assertArrayEquals(new String[0], parcel.flags);
- }
-}
diff --git a/tests/net/java/android/net/netlink/ConntrackMessageTest.java b/tests/net/java/android/net/netlink/ConntrackMessageTest.java
deleted file mode 100644
index 5c86757..0000000
--- a/tests/net/java/android/net/netlink/ConntrackMessageTest.java
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * 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.
- */
-
-package android.net.netlink;
-
-import static org.junit.Assert.assertArrayEquals;
-import static org.junit.Assume.assumeTrue;
-
-import android.system.OsConstants;
-
-import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
-
-import libcore.util.HexEncoding;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.net.Inet4Address;
-import java.net.InetAddress;
-import java.nio.ByteOrder;
-
-@RunWith(AndroidJUnit4.class)
-@SmallTest
-public class ConntrackMessageTest {
- private static final boolean USING_LE = (ByteOrder.nativeOrder() == ByteOrder.LITTLE_ENDIAN);
-
- // Example 1: TCP (192.168.43.209, 44333) -> (23.211.13.26, 443)
- public static final String CT_V4UPDATE_TCP_HEX =
- // struct nlmsghdr
- "50000000" + // length = 80
- "0001" + // type = (1 << 8) | 0
- "0501" + // flags
- "01000000" + // seqno = 1
- "00000000" + // pid = 0
- // struct nfgenmsg
- "02" + // nfgen_family = AF_INET
- "00" + // version = NFNETLINK_V0
- "0000" + // res_id
- // struct nlattr
- "3400" + // nla_len = 52
- "0180" + // nla_type = nested CTA_TUPLE_ORIG
- // struct nlattr
- "1400" + // nla_len = 20
- "0180" + // nla_type = nested CTA_TUPLE_IP
- "0800 0100 C0A82BD1" + // nla_type=CTA_IP_V4_SRC, ip=192.168.43.209
- "0800 0200 17D30D1A" + // nla_type=CTA_IP_V4_DST, ip=23.211.13.26
- // struct nlattr
- "1C00" + // nla_len = 28
- "0280" + // nla_type = nested CTA_TUPLE_PROTO
- "0500 0100 06 000000" + // nla_type=CTA_PROTO_NUM, proto=6
- "0600 0200 AD2D 0000" + // nla_type=CTA_PROTO_SRC_PORT, port=44333 (big endian)
- "0600 0300 01BB 0000" + // nla_type=CTA_PROTO_DST_PORT, port=443 (big endian)
- // struct nlattr
- "0800" + // nla_len = 8
- "0700" + // nla_type = CTA_TIMEOUT
- "00069780"; // nla_value = 432000 (big endian)
- public static final byte[] CT_V4UPDATE_TCP_BYTES =
- HexEncoding.decode(CT_V4UPDATE_TCP_HEX.replaceAll(" ", "").toCharArray(), false);
-
- // Example 2: UDP (100.96.167.146, 37069) -> (216.58.197.10, 443)
- public static final String CT_V4UPDATE_UDP_HEX =
- // struct nlmsghdr
- "50000000" + // length = 80
- "0001" + // type = (1 << 8) | 0
- "0501" + // flags
- "01000000" + // seqno = 1
- "00000000" + // pid = 0
- // struct nfgenmsg
- "02" + // nfgen_family = AF_INET
- "00" + // version = NFNETLINK_V0
- "0000" + // res_id
- // struct nlattr
- "3400" + // nla_len = 52
- "0180" + // nla_type = nested CTA_TUPLE_ORIG
- // struct nlattr
- "1400" + // nla_len = 20
- "0180" + // nla_type = nested CTA_TUPLE_IP
- "0800 0100 6460A792" + // nla_type=CTA_IP_V4_SRC, ip=100.96.167.146
- "0800 0200 D83AC50A" + // nla_type=CTA_IP_V4_DST, ip=216.58.197.10
- // struct nlattr
- "1C00" + // nla_len = 28
- "0280" + // nla_type = nested CTA_TUPLE_PROTO
- "0500 0100 11 000000" + // nla_type=CTA_PROTO_NUM, proto=17
- "0600 0200 90CD 0000" + // nla_type=CTA_PROTO_SRC_PORT, port=37069 (big endian)
- "0600 0300 01BB 0000" + // nla_type=CTA_PROTO_DST_PORT, port=443 (big endian)
- // struct nlattr
- "0800" + // nla_len = 8
- "0700" + // nla_type = CTA_TIMEOUT
- "000000B4"; // nla_value = 180 (big endian)
- public static final byte[] CT_V4UPDATE_UDP_BYTES =
- HexEncoding.decode(CT_V4UPDATE_UDP_HEX.replaceAll(" ", "").toCharArray(), false);
-
- @Test
- public void testConntrackIPv4TcpTimeoutUpdate() throws Exception {
- assumeTrue(USING_LE);
-
- final byte[] tcp = ConntrackMessage.newIPv4TimeoutUpdateRequest(
- OsConstants.IPPROTO_TCP,
- (Inet4Address) InetAddress.getByName("192.168.43.209"), 44333,
- (Inet4Address) InetAddress.getByName("23.211.13.26"), 443,
- 432000);
- assertArrayEquals(CT_V4UPDATE_TCP_BYTES, tcp);
- }
-
- @Test
- public void testConntrackIPv4UdpTimeoutUpdate() throws Exception {
- assumeTrue(USING_LE);
-
- final byte[] udp = ConntrackMessage.newIPv4TimeoutUpdateRequest(
- OsConstants.IPPROTO_UDP,
- (Inet4Address) InetAddress.getByName("100.96.167.146"), 37069,
- (Inet4Address) InetAddress.getByName("216.58.197.10"), 443,
- 180);
- assertArrayEquals(CT_V4UPDATE_UDP_BYTES, udp);
- }
-}
diff --git a/tests/net/java/android/net/netlink/InetDiagSocketTest.java b/tests/net/java/android/net/netlink/InetDiagSocketTest.java
deleted file mode 100644
index 84c5784..0000000
--- a/tests/net/java/android/net/netlink/InetDiagSocketTest.java
+++ /dev/null
@@ -1,448 +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 android.net.netlink;
-
-import static android.net.netlink.StructNlMsgHdr.NLM_F_DUMP;
-import static android.net.netlink.StructNlMsgHdr.NLM_F_REQUEST;
-import static android.system.OsConstants.AF_INET;
-import static android.system.OsConstants.AF_INET6;
-import static android.system.OsConstants.IPPROTO_TCP;
-import static android.system.OsConstants.IPPROTO_UDP;
-import static android.system.OsConstants.SOCK_DGRAM;
-import static android.system.OsConstants.SOCK_STREAM;
-
-import static org.junit.Assert.assertArrayEquals;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-import android.app.Instrumentation;
-import android.content.Context;
-import android.net.ConnectivityManager;
-import android.net.netlink.StructNlMsgHdr;
-import android.os.Process;
-import android.system.Os;
-
-import androidx.test.InstrumentationRegistry;
-import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
-
-import libcore.util.HexEncoding;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.io.FileDescriptor;
-import java.net.Inet4Address;
-import java.net.Inet6Address;
-import java.net.InetAddress;
-import java.net.InetSocketAddress;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-
-@RunWith(AndroidJUnit4.class)
-@SmallTest
-public class InetDiagSocketTest {
- private final String TAG = "InetDiagSocketTest";
- private ConnectivityManager mCm;
- private Context mContext;
- private final static int SOCKET_TIMEOUT_MS = 100;
-
- @Before
- public void setUp() throws Exception {
- Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
- mContext = instrumentation.getTargetContext();
- mCm = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
- }
-
- private class Connection {
- public int socketDomain;
- public int socketType;
- public InetAddress localAddress;
- public InetAddress remoteAddress;
- public InetAddress localhostAddress;
- public InetSocketAddress local;
- public InetSocketAddress remote;
- public int protocol;
- public FileDescriptor localFd;
- public FileDescriptor remoteFd;
-
- public FileDescriptor createSocket() throws Exception {
- return Os.socket(socketDomain, socketType, protocol);
- }
-
- public Connection(String to, String from) throws Exception {
- remoteAddress = InetAddress.getByName(to);
- if (from != null) {
- localAddress = InetAddress.getByName(from);
- } else {
- localAddress = (remoteAddress instanceof Inet4Address) ?
- Inet4Address.getByName("localhost") : Inet6Address.getByName("::");
- }
- if ((localAddress instanceof Inet4Address) && (remoteAddress instanceof Inet4Address)) {
- socketDomain = AF_INET;
- localhostAddress = Inet4Address.getByName("localhost");
- } else {
- socketDomain = AF_INET6;
- localhostAddress = Inet6Address.getByName("::");
- }
- }
-
- public void close() throws Exception {
- Os.close(localFd);
- }
- }
-
- private class TcpConnection extends Connection {
- public TcpConnection(String to, String from) throws Exception {
- super(to, from);
- protocol = IPPROTO_TCP;
- socketType = SOCK_STREAM;
-
- remoteFd = createSocket();
- Os.bind(remoteFd, remoteAddress, 0);
- Os.listen(remoteFd, 10);
- int remotePort = ((InetSocketAddress) Os.getsockname(remoteFd)).getPort();
-
- localFd = createSocket();
- Os.bind(localFd, localAddress, 0);
- Os.connect(localFd, remoteAddress, remotePort);
-
- local = (InetSocketAddress) Os.getsockname(localFd);
- remote = (InetSocketAddress) Os.getpeername(localFd);
- }
-
- public void close() throws Exception {
- super.close();
- Os.close(remoteFd);
- }
- }
- private class UdpConnection extends Connection {
- public UdpConnection(String to, String from) throws Exception {
- super(to, from);
- protocol = IPPROTO_UDP;
- socketType = SOCK_DGRAM;
-
- remoteFd = null;
- localFd = createSocket();
- Os.bind(localFd, localAddress, 0);
-
- Os.connect(localFd, remoteAddress, 7);
- local = (InetSocketAddress) Os.getsockname(localFd);
- remote = new InetSocketAddress(remoteAddress, 7);
- }
- }
-
- private void checkConnectionOwnerUid(int protocol, InetSocketAddress local,
- InetSocketAddress remote, boolean expectSuccess) {
- final int uid = mCm.getConnectionOwnerUid(protocol, local, remote);
-
- if (expectSuccess) {
- assertEquals(Process.myUid(), uid);
- } else {
- assertNotEquals(Process.myUid(), uid);
- }
- }
-
- private int findLikelyFreeUdpPort(UdpConnection conn) throws Exception {
- UdpConnection udp = new UdpConnection(conn.remoteAddress.getHostAddress(),
- conn.localAddress.getHostAddress());
- final int localPort = udp.local.getPort();
- udp.close();
- return localPort;
- }
-
- /**
- * Create a test connection for UDP and TCP sockets and verify that this
- * {protocol, local, remote} socket result in receiving a valid UID.
- */
- public void checkGetConnectionOwnerUid(String to, String from) throws Exception {
- TcpConnection tcp = new TcpConnection(to, from);
- checkConnectionOwnerUid(tcp.protocol, tcp.local, tcp.remote, true);
- checkConnectionOwnerUid(IPPROTO_UDP, tcp.local, tcp.remote, false);
- checkConnectionOwnerUid(tcp.protocol, new InetSocketAddress(0), tcp.remote, false);
- checkConnectionOwnerUid(tcp.protocol, tcp.local, new InetSocketAddress(0), false);
- tcp.close();
-
- UdpConnection udp = new UdpConnection(to,from);
- checkConnectionOwnerUid(udp.protocol, udp.local, udp.remote, true);
- checkConnectionOwnerUid(IPPROTO_TCP, udp.local, udp.remote, false);
- checkConnectionOwnerUid(udp.protocol, new InetSocketAddress(findLikelyFreeUdpPort(udp)),
- udp.remote, false);
- udp.close();
- }
-
- @Test
- public void testGetConnectionOwnerUid() throws Exception {
- checkGetConnectionOwnerUid("::", null);
- checkGetConnectionOwnerUid("::", "::");
- checkGetConnectionOwnerUid("0.0.0.0", null);
- checkGetConnectionOwnerUid("0.0.0.0", "0.0.0.0");
- checkGetConnectionOwnerUid("127.0.0.1", null);
- checkGetConnectionOwnerUid("127.0.0.1", "127.0.0.2");
- checkGetConnectionOwnerUid("::1", null);
- checkGetConnectionOwnerUid("::1", "::1");
- }
-
- /* Verify fix for b/141603906 */
- @Test
- public void testB141603906() throws Exception {
- final InetSocketAddress src = new InetSocketAddress(0);
- final InetSocketAddress dst = new InetSocketAddress(0);
- final int numThreads = 8;
- final int numSockets = 5000;
- final Thread[] threads = new Thread[numThreads];
-
- for (int i = 0; i < numThreads; i++) {
- threads[i] = new Thread(() -> {
- for (int j = 0; j < numSockets; j++) {
- mCm.getConnectionOwnerUid(IPPROTO_TCP, src, dst);
- }
- });
- }
-
- for (Thread thread : threads) {
- thread.start();
- }
-
- for (Thread thread : threads) {
- thread.join();
- }
- }
-
- // Hexadecimal representation of InetDiagReqV2 request.
- private static final String INET_DIAG_REQ_V2_UDP_INET4_HEX =
- // struct nlmsghdr
- "48000000" + // length = 72
- "1400" + // type = SOCK_DIAG_BY_FAMILY
- "0103" + // flags = NLM_F_REQUEST | NLM_F_DUMP
- "00000000" + // seqno
- "00000000" + // pid (0 == kernel)
- // struct inet_diag_req_v2
- "02" + // family = AF_INET
- "11" + // protcol = IPPROTO_UDP
- "00" + // idiag_ext
- "00" + // pad
- "ffffffff" + // idiag_states
- // inet_diag_sockid
- "a5de" + // idiag_sport = 42462
- "b971" + // idiag_dport = 47473
- "0a006402000000000000000000000000" + // idiag_src = 10.0.100.2
- "08080808000000000000000000000000" + // idiag_dst = 8.8.8.8
- "00000000" + // idiag_if
- "ffffffffffffffff"; // idiag_cookie = INET_DIAG_NOCOOKIE
- private static final byte[] INET_DIAG_REQ_V2_UDP_INET4_BYTES =
- HexEncoding.decode(INET_DIAG_REQ_V2_UDP_INET4_HEX.toCharArray(), false);
-
- @Test
- public void testInetDiagReqV2UdpInet4() throws Exception {
- InetSocketAddress local = new InetSocketAddress(InetAddress.getByName("10.0.100.2"),
- 42462);
- InetSocketAddress remote = new InetSocketAddress(InetAddress.getByName("8.8.8.8"),
- 47473);
- final byte[] msg = InetDiagMessage.InetDiagReqV2(IPPROTO_UDP, local, remote, AF_INET,
- (short) (NLM_F_REQUEST | NLM_F_DUMP));
- assertArrayEquals(INET_DIAG_REQ_V2_UDP_INET4_BYTES, msg);
- }
-
- // Hexadecimal representation of InetDiagReqV2 request.
- private static final String INET_DIAG_REQ_V2_TCP_INET6_HEX =
- // struct nlmsghdr
- "48000000" + // length = 72
- "1400" + // type = SOCK_DIAG_BY_FAMILY
- "0100" + // flags = NLM_F_REQUEST
- "00000000" + // seqno
- "00000000" + // pid (0 == kernel)
- // struct inet_diag_req_v2
- "0a" + // family = AF_INET6
- "06" + // protcol = IPPROTO_TCP
- "00" + // idiag_ext
- "00" + // pad
- "ffffffff" + // idiag_states
- // inet_diag_sockid
- "a5de" + // idiag_sport = 42462
- "b971" + // idiag_dport = 47473
- "fe8000000000000086c9b2fffe6aed4b" + // idiag_src = fe80::86c9:b2ff:fe6a:ed4b
- "08080808000000000000000000000000" + // idiag_dst = 8.8.8.8
- "00000000" + // idiag_if
- "ffffffffffffffff"; // idiag_cookie = INET_DIAG_NOCOOKIE
- private static final byte[] INET_DIAG_REQ_V2_TCP_INET6_BYTES =
- HexEncoding.decode(INET_DIAG_REQ_V2_TCP_INET6_HEX.toCharArray(), false);
-
- @Test
- public void testInetDiagReqV2TcpInet6() throws Exception {
- InetSocketAddress local = new InetSocketAddress(
- InetAddress.getByName("fe80::86c9:b2ff:fe6a:ed4b"), 42462);
- InetSocketAddress remote = new InetSocketAddress(InetAddress.getByName("8.8.8.8"),
- 47473);
- byte[] msg = InetDiagMessage.InetDiagReqV2(IPPROTO_TCP, local, remote, AF_INET6,
- NLM_F_REQUEST);
-
- assertArrayEquals(INET_DIAG_REQ_V2_TCP_INET6_BYTES, msg);
- }
-
- // Hexadecimal representation of InetDiagReqV2 request with extension, INET_DIAG_INFO.
- private static final String INET_DIAG_REQ_V2_TCP_INET_INET_DIAG_HEX =
- // struct nlmsghdr
- "48000000" + // length = 72
- "1400" + // type = SOCK_DIAG_BY_FAMILY
- "0100" + // flags = NLM_F_REQUEST
- "00000000" + // seqno
- "00000000" + // pid (0 == kernel)
- // struct inet_diag_req_v2
- "02" + // family = AF_INET
- "06" + // protcol = IPPROTO_TCP
- "02" + // idiag_ext = INET_DIAG_INFO
- "00" + // pad
- "ffffffff" + // idiag_states
- // inet_diag_sockid
- "3039" + // idiag_sport = 12345
- "d431" + // idiag_dport = 54321
- "01020304000000000000000000000000" + // idiag_src = 1.2.3.4
- "08080404000000000000000000000000" + // idiag_dst = 8.8.4.4
- "00000000" + // idiag_if
- "ffffffffffffffff"; // idiag_cookie = INET_DIAG_NOCOOKIE
-
- private static final byte[] INET_DIAG_REQ_V2_TCP_INET_INET_DIAG_BYTES =
- HexEncoding.decode(INET_DIAG_REQ_V2_TCP_INET_INET_DIAG_HEX.toCharArray(), false);
- private static final int TCP_ALL_STATES = 0xffffffff;
- @Test
- public void testInetDiagReqV2TcpInetWithExt() throws Exception {
- InetSocketAddress local = new InetSocketAddress(
- InetAddress.getByName("1.2.3.4"), 12345);
- InetSocketAddress remote = new InetSocketAddress(InetAddress.getByName("8.8.4.4"),
- 54321);
- byte[] msg = InetDiagMessage.InetDiagReqV2(IPPROTO_TCP, local, remote, AF_INET,
- NLM_F_REQUEST, 0 /* pad */, 2 /* idiagExt */, TCP_ALL_STATES);
-
- assertArrayEquals(INET_DIAG_REQ_V2_TCP_INET_INET_DIAG_BYTES, msg);
-
- local = new InetSocketAddress(
- InetAddress.getByName("fe80::86c9:b2ff:fe6a:ed4b"), 42462);
- remote = new InetSocketAddress(InetAddress.getByName("8.8.8.8"),
- 47473);
- msg = InetDiagMessage.InetDiagReqV2(IPPROTO_TCP, local, remote, AF_INET6,
- NLM_F_REQUEST, 0 /* pad */, 0 /* idiagExt */, TCP_ALL_STATES);
-
- assertArrayEquals(INET_DIAG_REQ_V2_TCP_INET6_BYTES, msg);
- }
-
- // Hexadecimal representation of InetDiagReqV2 request with no socket specified.
- private static final String INET_DIAG_REQ_V2_TCP_INET6_NO_ID_SPECIFIED_HEX =
- // struct nlmsghdr
- "48000000" + // length = 72
- "1400" + // type = SOCK_DIAG_BY_FAMILY
- "0100" + // flags = NLM_F_REQUEST
- "00000000" + // seqno
- "00000000" + // pid (0 == kernel)
- // struct inet_diag_req_v2
- "0a" + // family = AF_INET6
- "06" + // protcol = IPPROTO_TCP
- "00" + // idiag_ext
- "00" + // pad
- "ffffffff" + // idiag_states
- // inet_diag_sockid
- "0000" + // idiag_sport
- "0000" + // idiag_dport
- "00000000000000000000000000000000" + // idiag_src
- "00000000000000000000000000000000" + // idiag_dst
- "00000000" + // idiag_if
- "0000000000000000"; // idiag_cookie
-
- private static final byte[] INET_DIAG_REQ_V2_TCP_INET6_NO_ID_SPECIFED_BYTES =
- HexEncoding.decode(INET_DIAG_REQ_V2_TCP_INET6_NO_ID_SPECIFIED_HEX.toCharArray(), false);
-
- @Test
- public void testInetDiagReqV2TcpInet6NoIdSpecified() throws Exception {
- InetSocketAddress local = new InetSocketAddress(
- InetAddress.getByName("fe80::fe6a:ed4b"), 12345);
- InetSocketAddress remote = new InetSocketAddress(InetAddress.getByName("8.8.4.4"),
- 54321);
- // Verify no socket specified if either local or remote socket address is null.
- byte[] msgExt = InetDiagMessage.InetDiagReqV2(IPPROTO_TCP, null, null, AF_INET6,
- NLM_F_REQUEST, 0 /* pad */, 0 /* idiagExt */, TCP_ALL_STATES);
- byte[] msg;
- try {
- msg = InetDiagMessage.InetDiagReqV2(IPPROTO_TCP, null, remote, AF_INET6,
- NLM_F_REQUEST);
- fail("Both remote and local should be null, expected UnknownHostException");
- } catch (NullPointerException e) {
- }
-
- try {
- msg = InetDiagMessage.InetDiagReqV2(IPPROTO_TCP, local, null, AF_INET6,
- NLM_F_REQUEST, 0 /* pad */, 0 /* idiagExt */, TCP_ALL_STATES);
- fail("Both remote and local should be null, expected UnknownHostException");
- } catch (NullPointerException e) {
- }
-
- msg = InetDiagMessage.InetDiagReqV2(IPPROTO_TCP, null, null, AF_INET6,
- NLM_F_REQUEST, 0 /* pad */, 0 /* idiagExt */, TCP_ALL_STATES);
- assertArrayEquals(INET_DIAG_REQ_V2_TCP_INET6_NO_ID_SPECIFED_BYTES, msg);
- assertArrayEquals(INET_DIAG_REQ_V2_TCP_INET6_NO_ID_SPECIFED_BYTES, msgExt);
- }
-
- // Hexadecimal representation of InetDiagReqV2 request.
- private static final String INET_DIAG_MSG_HEX =
- // struct nlmsghdr
- "58000000" + // length = 88
- "1400" + // type = SOCK_DIAG_BY_FAMILY
- "0200" + // flags = NLM_F_MULTI
- "00000000" + // seqno
- "f5220000" + // pid (0 == kernel)
- // struct inet_diag_msg
- "0a" + // family = AF_INET6
- "01" + // idiag_state
- "00" + // idiag_timer
- "00" + // idiag_retrans
- // inet_diag_sockid
- "a817" + // idiag_sport = 43031
- "960f" + // idiag_dport = 38415
- "fe8000000000000086c9b2fffe6aed4b" + // idiag_src = fe80::86c9:b2ff:fe6a:ed4b
- "00000000000000000000ffff08080808" + // idiag_dst = 8.8.8.8
- "00000000" + // idiag_if
- "ffffffffffffffff" + // idiag_cookie = INET_DIAG_NOCOOKIE
- "00000000" + // idiag_expires
- "00000000" + // idiag_rqueue
- "00000000" + // idiag_wqueue
- "a3270000" + // idiag_uid
- "A57E1900"; // idiag_inode
- private static final byte[] INET_DIAG_MSG_BYTES =
- HexEncoding.decode(INET_DIAG_MSG_HEX.toCharArray(), false);
-
- @Test
- public void testParseInetDiagResponse() throws Exception {
- final ByteBuffer byteBuffer = ByteBuffer.wrap(INET_DIAG_MSG_BYTES);
- byteBuffer.order(ByteOrder.LITTLE_ENDIAN);
- final NetlinkMessage msg = NetlinkMessage.parse(byteBuffer);
- assertNotNull(msg);
-
- assertTrue(msg instanceof InetDiagMessage);
- final InetDiagMessage inetDiagMsg = (InetDiagMessage) msg;
- assertEquals(10147, inetDiagMsg.mStructInetDiagMsg.idiag_uid);
-
- final StructNlMsgHdr hdr = inetDiagMsg.getHeader();
- assertNotNull(hdr);
- assertEquals(NetlinkConstants.SOCK_DIAG_BY_FAMILY, hdr.nlmsg_type);
- assertEquals(StructNlMsgHdr.NLM_F_MULTI, hdr.nlmsg_flags);
- assertEquals(0, hdr.nlmsg_seq);
- assertEquals(8949, hdr.nlmsg_pid);
- }
-}
diff --git a/tests/net/java/android/net/netlink/NetlinkErrorMessageTest.java b/tests/net/java/android/net/netlink/NetlinkErrorMessageTest.java
deleted file mode 100644
index 44ab605..0000000
--- a/tests/net/java/android/net/netlink/NetlinkErrorMessageTest.java
+++ /dev/null
@@ -1,94 +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 android.net.netlink;
-
-import static android.net.netlink.StructNlMsgHdr.NLM_F_ACK;
-import static android.net.netlink.StructNlMsgHdr.NLM_F_REPLACE;
-import static android.net.netlink.StructNlMsgHdr.NLM_F_REQUEST;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-
-import android.net.netlink.NetlinkConstants;
-import android.net.netlink.NetlinkErrorMessage;
-import android.net.netlink.NetlinkMessage;
-import android.net.netlink.StructNlMsgErr;
-
-import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
-
-import libcore.util.HexEncoding;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-
-@RunWith(AndroidJUnit4.class)
-@SmallTest
-public class NetlinkErrorMessageTest {
- private final String TAG = "NetlinkErrorMessageTest";
-
- // Hexadecimal representation of packet capture.
- public static final String NLM_ERROR_OK_HEX =
- // struct nlmsghdr
- "24000000" + // length = 36
- "0200" + // type = 2 (NLMSG_ERROR)
- "0000" + // flags
- "26350000" + // seqno
- "64100000" + // pid = userspace process
- // error integer
- "00000000" + // "errno" (0 == OK)
- // struct nlmsghdr
- "30000000" + // length (48) of original request
- "1C00" + // type = 28 (RTM_NEWNEIGH)
- "0501" + // flags (NLM_F_REQUEST | NLM_F_ACK | NLM_F_REPLACE)
- "26350000" + // seqno
- "00000000"; // pid = kernel
- public static final byte[] NLM_ERROR_OK =
- HexEncoding.decode(NLM_ERROR_OK_HEX.toCharArray(), false);
-
- @Test
- public void testParseNlmErrorOk() {
- final ByteBuffer byteBuffer = ByteBuffer.wrap(NLM_ERROR_OK);
- byteBuffer.order(ByteOrder.LITTLE_ENDIAN); // For testing.
- final NetlinkMessage msg = NetlinkMessage.parse(byteBuffer);
- assertNotNull(msg);
- assertTrue(msg instanceof NetlinkErrorMessage);
- final NetlinkErrorMessage errorMsg = (NetlinkErrorMessage) msg;
-
- final StructNlMsgHdr hdr = errorMsg.getHeader();
- assertNotNull(hdr);
- assertEquals(36, hdr.nlmsg_len);
- assertEquals(NetlinkConstants.NLMSG_ERROR, hdr.nlmsg_type);
- assertEquals(0, hdr.nlmsg_flags);
- assertEquals(13606, hdr.nlmsg_seq);
- assertEquals(4196, hdr.nlmsg_pid);
-
- final StructNlMsgErr err = errorMsg.getNlMsgError();
- assertNotNull(err);
- assertEquals(0, err.error);
- assertNotNull(err.msg);
- assertEquals(48, err.msg.nlmsg_len);
- assertEquals(NetlinkConstants.RTM_NEWNEIGH, err.msg.nlmsg_type);
- assertEquals((NLM_F_REQUEST | NLM_F_ACK | NLM_F_REPLACE), err.msg.nlmsg_flags);
- assertEquals(13606, err.msg.nlmsg_seq);
- assertEquals(0, err.msg.nlmsg_pid);
- }
-}
diff --git a/tests/net/java/android/net/netlink/NetlinkSocketTest.java b/tests/net/java/android/net/netlink/NetlinkSocketTest.java
deleted file mode 100644
index 3916578..0000000
--- a/tests/net/java/android/net/netlink/NetlinkSocketTest.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 android.net.netlink;
-
-import static android.net.netlink.NetlinkSocket.DEFAULT_RECV_BUFSIZE;
-import static android.system.OsConstants.NETLINK_ROUTE;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-
-import android.net.netlink.NetlinkSocket;
-import android.net.netlink.RtNetlinkNeighborMessage;
-import android.net.netlink.StructNlMsgHdr;
-import android.system.NetlinkSocketAddress;
-import android.system.Os;
-
-import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
-
-import libcore.io.IoUtils;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.io.FileDescriptor;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-
-@RunWith(AndroidJUnit4.class)
-@SmallTest
-public class NetlinkSocketTest {
- private final String TAG = "NetlinkSocketTest";
-
- @Test
- public void testBasicWorkingGetNeighborsQuery() throws Exception {
- final FileDescriptor fd = NetlinkSocket.forProto(NETLINK_ROUTE);
- assertNotNull(fd);
-
- NetlinkSocket.connectToKernel(fd);
-
- final NetlinkSocketAddress localAddr = (NetlinkSocketAddress) Os.getsockname(fd);
- assertNotNull(localAddr);
- assertEquals(0, localAddr.getGroupsMask());
- assertTrue(0 != localAddr.getPortId());
-
- final int TEST_SEQNO = 5;
- final byte[] req = RtNetlinkNeighborMessage.newGetNeighborsRequest(TEST_SEQNO);
- assertNotNull(req);
-
- final long TIMEOUT = 500;
- assertEquals(req.length, NetlinkSocket.sendMessage(fd, req, 0, req.length, TIMEOUT));
-
- int neighMessageCount = 0;
- int doneMessageCount = 0;
-
- while (doneMessageCount == 0) {
- ByteBuffer response = NetlinkSocket.recvMessage(fd, DEFAULT_RECV_BUFSIZE, TIMEOUT);
- assertNotNull(response);
- assertTrue(StructNlMsgHdr.STRUCT_SIZE <= response.limit());
- assertEquals(0, response.position());
- assertEquals(ByteOrder.nativeOrder(), response.order());
-
- // Verify the messages at least appears minimally reasonable.
- while (response.remaining() > 0) {
- final NetlinkMessage msg = NetlinkMessage.parse(response);
- assertNotNull(msg);
- final StructNlMsgHdr hdr = msg.getHeader();
- assertNotNull(hdr);
-
- if (hdr.nlmsg_type == NetlinkConstants.NLMSG_DONE) {
- doneMessageCount++;
- continue;
- }
-
- assertEquals(NetlinkConstants.RTM_NEWNEIGH, hdr.nlmsg_type);
- assertTrue(msg instanceof RtNetlinkNeighborMessage);
- assertTrue((hdr.nlmsg_flags & StructNlMsgHdr.NLM_F_MULTI) != 0);
- assertEquals(TEST_SEQNO, hdr.nlmsg_seq);
- assertEquals(localAddr.getPortId(), hdr.nlmsg_pid);
-
- neighMessageCount++;
- }
- }
-
- assertEquals(1, doneMessageCount);
- // TODO: make sure this test passes sanely in airplane mode.
- assertTrue(neighMessageCount > 0);
-
- IoUtils.closeQuietly(fd);
- }
-}
diff --git a/tests/net/java/android/net/netlink/RtNetlinkNeighborMessageTest.java b/tests/net/java/android/net/netlink/RtNetlinkNeighborMessageTest.java
deleted file mode 100644
index 8162522..0000000
--- a/tests/net/java/android/net/netlink/RtNetlinkNeighborMessageTest.java
+++ /dev/null
@@ -1,270 +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 android.net.netlink;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-
-import android.net.netlink.NetlinkConstants;
-import android.net.netlink.NetlinkMessage;
-import android.net.netlink.RtNetlinkNeighborMessage;
-import android.net.netlink.StructNdMsg;
-import android.net.netlink.StructNlMsgHdr;
-import android.system.OsConstants;
-
-import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
-
-import libcore.util.HexEncoding;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.net.Inet4Address;
-import java.net.InetAddress;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-import java.util.Arrays;
-
-@RunWith(AndroidJUnit4.class)
-@SmallTest
-public class RtNetlinkNeighborMessageTest {
- private final String TAG = "RtNetlinkNeighborMessageTest";
-
- // Hexadecimal representation of packet capture.
- public static final String RTM_DELNEIGH_HEX =
- // struct nlmsghdr
- "4c000000" + // length = 76
- "1d00" + // type = 29 (RTM_DELNEIGH)
- "0000" + // flags
- "00000000" + // seqno
- "00000000" + // pid (0 == kernel)
- // struct ndmsg
- "02" + // family
- "00" + // pad1
- "0000" + // pad2
- "15000000" + // interface index (21 == wlan0, on test device)
- "0400" + // NUD state (0x04 == NUD_STALE)
- "00" + // flags
- "01" + // type
- // struct nlattr: NDA_DST
- "0800" + // length = 8
- "0100" + // type (1 == NDA_DST, for neighbor messages)
- "c0a89ffe" + // IPv4 address (== 192.168.159.254)
- // struct nlattr: NDA_LLADDR
- "0a00" + // length = 10
- "0200" + // type (2 == NDA_LLADDR, for neighbor messages)
- "00005e000164" + // MAC Address (== 00:00:5e:00:01:64)
- "0000" + // padding, for 4 byte alignment
- // struct nlattr: NDA_PROBES
- "0800" + // length = 8
- "0400" + // type (4 == NDA_PROBES, for neighbor messages)
- "01000000" + // number of probes
- // struct nlattr: NDA_CACHEINFO
- "1400" + // length = 20
- "0300" + // type (3 == NDA_CACHEINFO, for neighbor messages)
- "05190000" + // ndm_used, as "clock ticks ago"
- "05190000" + // ndm_confirmed, as "clock ticks ago"
- "190d0000" + // ndm_updated, as "clock ticks ago"
- "00000000"; // ndm_refcnt
- public static final byte[] RTM_DELNEIGH =
- HexEncoding.decode(RTM_DELNEIGH_HEX.toCharArray(), false);
-
- // Hexadecimal representation of packet capture.
- public static final String RTM_NEWNEIGH_HEX =
- // struct nlmsghdr
- "58000000" + // length = 88
- "1c00" + // type = 28 (RTM_NEWNEIGH)
- "0000" + // flags
- "00000000" + // seqno
- "00000000" + // pid (0 == kernel)
- // struct ndmsg
- "0a" + // family
- "00" + // pad1
- "0000" + // pad2
- "15000000" + // interface index (21 == wlan0, on test device)
- "0400" + // NUD state (0x04 == NUD_STALE)
- "80" + // flags
- "01" + // type
- // struct nlattr: NDA_DST
- "1400" + // length = 20
- "0100" + // type (1 == NDA_DST, for neighbor messages)
- "fe8000000000000086c9b2fffe6aed4b" + // IPv6 address (== fe80::86c9:b2ff:fe6a:ed4b)
- // struct nlattr: NDA_LLADDR
- "0a00" + // length = 10
- "0200" + // type (2 == NDA_LLADDR, for neighbor messages)
- "84c9b26aed4b" + // MAC Address (== 84:c9:b2:6a:ed:4b)
- "0000" + // padding, for 4 byte alignment
- // struct nlattr: NDA_PROBES
- "0800" + // length = 8
- "0400" + // type (4 == NDA_PROBES, for neighbor messages)
- "01000000" + // number of probes
- // struct nlattr: NDA_CACHEINFO
- "1400" + // length = 20
- "0300" + // type (3 == NDA_CACHEINFO, for neighbor messages)
- "eb0e0000" + // ndm_used, as "clock ticks ago"
- "861f0000" + // ndm_confirmed, as "clock ticks ago"
- "00000000" + // ndm_updated, as "clock ticks ago"
- "05000000"; // ndm_refcnt
- public static final byte[] RTM_NEWNEIGH =
- HexEncoding.decode(RTM_NEWNEIGH_HEX.toCharArray(), false);
-
- // An example of the full response from an RTM_GETNEIGH query.
- private static final String RTM_GETNEIGH_RESPONSE_HEX =
- // <-- struct nlmsghr -->|<-- struct ndmsg -->|<-- struct nlattr: NDA_DST -->|<-- NDA_LLADDR -->|<-- NDA_PROBES -->|<-- NDA_CACHEINFO -->|
- "58000000 1c00 0200 00000000 3e2b0000 0a 00 0000 15000000 4000 00 05 1400 0100 ff020000000000000000000000000001 0a00 0200 333300000001 0000 0800 0400 00000000 1400 0300 a2280000 32110000 32110000 01000000" +
- "58000000 1c00 0200 00000000 3e2b0000 0a 00 0000 15000000 4000 00 05 1400 0100 ff0200000000000000000001ff000001 0a00 0200 3333ff000001 0000 0800 0400 00000000 1400 0300 0d280000 9d100000 9d100000 00000000" +
- "58000000 1c00 0200 00000000 3e2b0000 0a 00 0000 15000000 0400 80 01 1400 0100 20010db800040ca00000000000000001 0a00 0200 84c9b26aed4b 0000 0800 0400 04000000 1400 0300 90100000 90100000 90080000 01000000" +
- "58000000 1c00 0200 00000000 3e2b0000 0a 00 0000 15000000 4000 00 05 1400 0100 ff0200000000000000000001ff47da19 0a00 0200 3333ff47da19 0000 0800 0400 00000000 1400 0300 a1280000 31110000 31110000 01000000" +
- "58000000 1c00 0200 00000000 3e2b0000 0a 00 0000 14000000 4000 00 05 1400 0100 ff020000000000000000000000000016 0a00 0200 333300000016 0000 0800 0400 00000000 1400 0300 912a0000 21130000 21130000 00000000" +
- "58000000 1c00 0200 00000000 3e2b0000 0a 00 0000 14000000 4000 00 05 1400 0100 ff0200000000000000000001ffeace3b 0a00 0200 3333ffeace3b 0000 0800 0400 00000000 1400 0300 922a0000 22130000 22130000 00000000" +
- "58000000 1c00 0200 00000000 3e2b0000 0a 00 0000 15000000 4000 00 05 1400 0100 ff0200000000000000000001ff5c2a83 0a00 0200 3333ff5c2a83 0000 0800 0400 00000000 1400 0300 391c0000 c9040000 c9040000 01000000" +
- "58000000 1c00 0200 00000000 3e2b0000 0a 00 0000 01000000 4000 00 02 1400 0100 00000000000000000000000000000000 0a00 0200 000000000000 0000 0800 0400 00000000 1400 0300 cd180200 5d010200 5d010200 08000000" +
- "58000000 1c00 0200 00000000 3e2b0000 0a 00 0000 15000000 4000 00 05 1400 0100 ff020000000000000000000000000002 0a00 0200 333300000002 0000 0800 0400 00000000 1400 0300 352a0000 c5120000 c5120000 00000000" +
- "58000000 1c00 0200 00000000 3e2b0000 0a 00 0000 15000000 4000 00 05 1400 0100 ff020000000000000000000000000016 0a00 0200 333300000016 0000 0800 0400 00000000 1400 0300 982a0000 28130000 28130000 00000000" +
- "58000000 1c00 0200 00000000 3e2b0000 0a 00 0000 15000000 0800 80 01 1400 0100 fe8000000000000086c9b2fffe6aed4b 0a00 0200 84c9b26aed4b 0000 0800 0400 00000000 1400 0300 23000000 24000000 57000000 13000000" +
- "58000000 1c00 0200 00000000 3e2b0000 0a 00 0000 15000000 4000 00 05 1400 0100 ff0200000000000000000001ffeace3b 0a00 0200 3333ffeace3b 0000 0800 0400 00000000 1400 0300 992a0000 29130000 29130000 01000000" +
- "58000000 1c00 0200 00000000 3e2b0000 0a 00 0000 14000000 4000 00 05 1400 0100 ff020000000000000000000000000002 0a00 0200 333300000002 0000 0800 0400 00000000 1400 0300 2e2a0000 be120000 be120000 00000000" +
- "44000000 1c00 0200 00000000 3e2b0000 02 00 0000 18000000 4000 00 03 0800 0100 00000000 0400 0200 0800 0400 00000000 1400 0300 75280000 05110000 05110000 22000000";
- public static final byte[] RTM_GETNEIGH_RESPONSE =
- HexEncoding.decode(RTM_GETNEIGH_RESPONSE_HEX.replaceAll(" ", "").toCharArray(), false);
-
- @Test
- public void testParseRtmDelNeigh() {
- final ByteBuffer byteBuffer = ByteBuffer.wrap(RTM_DELNEIGH);
- byteBuffer.order(ByteOrder.LITTLE_ENDIAN); // For testing.
- final NetlinkMessage msg = NetlinkMessage.parse(byteBuffer);
- assertNotNull(msg);
- assertTrue(msg instanceof RtNetlinkNeighborMessage);
- final RtNetlinkNeighborMessage neighMsg = (RtNetlinkNeighborMessage) msg;
-
- final StructNlMsgHdr hdr = neighMsg.getHeader();
- assertNotNull(hdr);
- assertEquals(76, hdr.nlmsg_len);
- assertEquals(NetlinkConstants.RTM_DELNEIGH, hdr.nlmsg_type);
- assertEquals(0, hdr.nlmsg_flags);
- assertEquals(0, hdr.nlmsg_seq);
- assertEquals(0, hdr.nlmsg_pid);
-
- final StructNdMsg ndmsgHdr = neighMsg.getNdHeader();
- assertNotNull(ndmsgHdr);
- assertEquals((byte) OsConstants.AF_INET, ndmsgHdr.ndm_family);
- assertEquals(21, ndmsgHdr.ndm_ifindex);
- assertEquals(StructNdMsg.NUD_STALE, ndmsgHdr.ndm_state);
- final InetAddress destination = neighMsg.getDestination();
- assertNotNull(destination);
- assertEquals(InetAddress.parseNumericAddress("192.168.159.254"), destination);
- }
-
- @Test
- public void testParseRtmNewNeigh() {
- final ByteBuffer byteBuffer = ByteBuffer.wrap(RTM_NEWNEIGH);
- byteBuffer.order(ByteOrder.LITTLE_ENDIAN); // For testing.
- final NetlinkMessage msg = NetlinkMessage.parse(byteBuffer);
- assertNotNull(msg);
- assertTrue(msg instanceof RtNetlinkNeighborMessage);
- final RtNetlinkNeighborMessage neighMsg = (RtNetlinkNeighborMessage) msg;
-
- final StructNlMsgHdr hdr = neighMsg.getHeader();
- assertNotNull(hdr);
- assertEquals(88, hdr.nlmsg_len);
- assertEquals(NetlinkConstants.RTM_NEWNEIGH, hdr.nlmsg_type);
- assertEquals(0, hdr.nlmsg_flags);
- assertEquals(0, hdr.nlmsg_seq);
- assertEquals(0, hdr.nlmsg_pid);
-
- final StructNdMsg ndmsgHdr = neighMsg.getNdHeader();
- assertNotNull(ndmsgHdr);
- assertEquals((byte) OsConstants.AF_INET6, ndmsgHdr.ndm_family);
- assertEquals(21, ndmsgHdr.ndm_ifindex);
- assertEquals(StructNdMsg.NUD_STALE, ndmsgHdr.ndm_state);
- final InetAddress destination = neighMsg.getDestination();
- assertNotNull(destination);
- assertEquals(InetAddress.parseNumericAddress("fe80::86c9:b2ff:fe6a:ed4b"), destination);
- }
-
- @Test
- public void testParseRtmGetNeighResponse() {
- final ByteBuffer byteBuffer = ByteBuffer.wrap(RTM_GETNEIGH_RESPONSE);
- byteBuffer.order(ByteOrder.LITTLE_ENDIAN); // For testing.
-
- int messageCount = 0;
- while (byteBuffer.remaining() > 0) {
- final NetlinkMessage msg = NetlinkMessage.parse(byteBuffer);
- assertNotNull(msg);
- assertTrue(msg instanceof RtNetlinkNeighborMessage);
- final RtNetlinkNeighborMessage neighMsg = (RtNetlinkNeighborMessage) msg;
-
- final StructNlMsgHdr hdr = neighMsg.getHeader();
- assertNotNull(hdr);
- assertEquals(NetlinkConstants.RTM_NEWNEIGH, hdr.nlmsg_type);
- assertEquals(StructNlMsgHdr.NLM_F_MULTI, hdr.nlmsg_flags);
- assertEquals(0, hdr.nlmsg_seq);
- assertEquals(11070, hdr.nlmsg_pid);
-
- messageCount++;
- }
- // TODO: add more detailed spot checks.
- assertEquals(14, messageCount);
- }
-
- @Test
- public void testCreateRtmNewNeighMessage() {
- final int seqNo = 2635;
- final int ifIndex = 14;
- final byte[] llAddr =
- new byte[] { (byte) 1, (byte) 2, (byte) 3, (byte) 4, (byte) 5, (byte) 6 };
-
- // Hexadecimal representation of our created packet.
- final String expectedNewNeighHex =
- // struct nlmsghdr
- "30000000" + // length = 48
- "1c00" + // type = 28 (RTM_NEWNEIGH)
- "0501" + // flags (NLM_F_REQUEST | NLM_F_ACK | NLM_F_REPLACE)
- "4b0a0000" + // seqno
- "00000000" + // pid (0 == kernel)
- // struct ndmsg
- "02" + // family
- "00" + // pad1
- "0000" + // pad2
- "0e000000" + // interface index (14)
- "0800" + // NUD state (0x08 == NUD_DELAY)
- "00" + // flags
- "00" + // type
- // struct nlattr: NDA_DST
- "0800" + // length = 8
- "0100" + // type (1 == NDA_DST, for neighbor messages)
- "7f000001" + // IPv4 address (== 127.0.0.1)
- // struct nlattr: NDA_LLADDR
- "0a00" + // length = 10
- "0200" + // type (2 == NDA_LLADDR, for neighbor messages)
- "010203040506" + // MAC Address (== 01:02:03:04:05:06)
- "0000"; // padding, for 4 byte alignment
- final byte[] expectedNewNeigh =
- HexEncoding.decode(expectedNewNeighHex.toCharArray(), false);
-
- final byte[] bytes = RtNetlinkNeighborMessage.newNewNeighborMessage(
- seqNo, Inet4Address.LOOPBACK, StructNdMsg.NUD_DELAY, ifIndex, llAddr);
- if (!Arrays.equals(expectedNewNeigh, bytes)) {
- assertEquals(expectedNewNeigh.length, bytes.length);
- for (int i = 0; i < Math.min(expectedNewNeigh.length, bytes.length); i++) {
- assertEquals(expectedNewNeigh[i], bytes[i]);
- }
- }
- }
-}
diff --git a/tests/net/java/android/net/shared/Inet4AddressUtilsTest.java b/tests/net/java/android/net/shared/Inet4AddressUtilsTest.java
deleted file mode 100644
index 35f8c79..0000000
--- a/tests/net/java/android/net/shared/Inet4AddressUtilsTest.java
+++ /dev/null
@@ -1,210 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.shared;
-
-import static android.net.shared.Inet4AddressUtils.getBroadcastAddress;
-import static android.net.shared.Inet4AddressUtils.getImplicitNetmask;
-import static android.net.shared.Inet4AddressUtils.getPrefixMaskAsInet4Address;
-import static android.net.shared.Inet4AddressUtils.inet4AddressToIntHTH;
-import static android.net.shared.Inet4AddressUtils.inet4AddressToIntHTL;
-import static android.net.shared.Inet4AddressUtils.intToInet4AddressHTH;
-import static android.net.shared.Inet4AddressUtils.intToInet4AddressHTL;
-import static android.net.shared.Inet4AddressUtils.netmaskToPrefixLength;
-import static android.net.shared.Inet4AddressUtils.prefixLengthToV4NetmaskIntHTH;
-import static android.net.shared.Inet4AddressUtils.prefixLengthToV4NetmaskIntHTL;
-
-import static junit.framework.Assert.assertEquals;
-
-import static org.junit.Assert.fail;
-
-import android.net.InetAddresses;
-
-import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.net.Inet4Address;
-
-@RunWith(AndroidJUnit4.class)
-@SmallTest
-public class Inet4AddressUtilsTest {
-
- @Test
- public void testInet4AddressToIntHTL() {
- assertEquals(0, inet4AddressToIntHTL(ipv4Address("0.0.0.0")));
- assertEquals(0x000080ff, inet4AddressToIntHTL(ipv4Address("255.128.0.0")));
- assertEquals(0x0080ff0a, inet4AddressToIntHTL(ipv4Address("10.255.128.0")));
- assertEquals(0x00feff0a, inet4AddressToIntHTL(ipv4Address("10.255.254.0")));
- assertEquals(0xfeffa8c0, inet4AddressToIntHTL(ipv4Address("192.168.255.254")));
- assertEquals(0xffffa8c0, inet4AddressToIntHTL(ipv4Address("192.168.255.255")));
- }
-
- @Test
- public void testIntToInet4AddressHTL() {
- assertEquals(ipv4Address("0.0.0.0"), intToInet4AddressHTL(0));
- assertEquals(ipv4Address("255.128.0.0"), intToInet4AddressHTL(0x000080ff));
- assertEquals(ipv4Address("10.255.128.0"), intToInet4AddressHTL(0x0080ff0a));
- assertEquals(ipv4Address("10.255.254.0"), intToInet4AddressHTL(0x00feff0a));
- assertEquals(ipv4Address("192.168.255.254"), intToInet4AddressHTL(0xfeffa8c0));
- assertEquals(ipv4Address("192.168.255.255"), intToInet4AddressHTL(0xffffa8c0));
- }
-
- @Test
- public void testInet4AddressToIntHTH() {
- assertEquals(0, inet4AddressToIntHTH(ipv4Address("0.0.0.0")));
- assertEquals(0xff800000, inet4AddressToIntHTH(ipv4Address("255.128.0.0")));
- assertEquals(0x0aff8000, inet4AddressToIntHTH(ipv4Address("10.255.128.0")));
- assertEquals(0x0afffe00, inet4AddressToIntHTH(ipv4Address("10.255.254.0")));
- assertEquals(0xc0a8fffe, inet4AddressToIntHTH(ipv4Address("192.168.255.254")));
- assertEquals(0xc0a8ffff, inet4AddressToIntHTH(ipv4Address("192.168.255.255")));
- }
-
- @Test
- public void testIntToInet4AddressHTH() {
- assertEquals(ipv4Address("0.0.0.0"), intToInet4AddressHTH(0));
- assertEquals(ipv4Address("255.128.0.0"), intToInet4AddressHTH(0xff800000));
- assertEquals(ipv4Address("10.255.128.0"), intToInet4AddressHTH(0x0aff8000));
- assertEquals(ipv4Address("10.255.254.0"), intToInet4AddressHTH(0x0afffe00));
- assertEquals(ipv4Address("192.168.255.254"), intToInet4AddressHTH(0xc0a8fffe));
- assertEquals(ipv4Address("192.168.255.255"), intToInet4AddressHTH(0xc0a8ffff));
- }
-
-
- @Test
- public void testPrefixLengthToV4NetmaskIntHTL() {
- assertEquals(0, prefixLengthToV4NetmaskIntHTL(0));
- assertEquals(0x000080ff /* 255.128.0.0 */, prefixLengthToV4NetmaskIntHTL(9));
- assertEquals(0x0080ffff /* 255.255.128.0 */, prefixLengthToV4NetmaskIntHTL(17));
- assertEquals(0x00feffff /* 255.255.254.0 */, prefixLengthToV4NetmaskIntHTL(23));
- assertEquals(0xfeffffff /* 255.255.255.254 */, prefixLengthToV4NetmaskIntHTL(31));
- assertEquals(0xffffffff /* 255.255.255.255 */, prefixLengthToV4NetmaskIntHTL(32));
- }
-
- @Test
- public void testPrefixLengthToV4NetmaskIntHTH() {
- assertEquals(0, prefixLengthToV4NetmaskIntHTH(0));
- assertEquals(0xff800000 /* 255.128.0.0 */, prefixLengthToV4NetmaskIntHTH(9));
- assertEquals(0xffff8000 /* 255.255.128.0 */, prefixLengthToV4NetmaskIntHTH(17));
- assertEquals(0xfffffe00 /* 255.255.254.0 */, prefixLengthToV4NetmaskIntHTH(23));
- assertEquals(0xfffffffe /* 255.255.255.254 */, prefixLengthToV4NetmaskIntHTH(31));
- assertEquals(0xffffffff /* 255.255.255.255 */, prefixLengthToV4NetmaskIntHTH(32));
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void testPrefixLengthToV4NetmaskIntHTH_NegativeLength() {
- prefixLengthToV4NetmaskIntHTH(-1);
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void testPrefixLengthToV4NetmaskIntHTH_LengthTooLarge() {
- prefixLengthToV4NetmaskIntHTH(33);
- }
-
- private void checkAddressMasking(String expectedAddr, String addr, int prefixLength) {
- final int prefix = prefixLengthToV4NetmaskIntHTH(prefixLength);
- final int addrInt = inet4AddressToIntHTH(ipv4Address(addr));
- assertEquals(ipv4Address(expectedAddr), intToInet4AddressHTH(prefix & addrInt));
- }
-
- @Test
- public void testPrefixLengthToV4NetmaskIntHTH_MaskAddr() {
- checkAddressMasking("192.168.0.0", "192.168.128.1", 16);
- checkAddressMasking("255.240.0.0", "255.255.255.255", 12);
- checkAddressMasking("255.255.255.255", "255.255.255.255", 32);
- checkAddressMasking("0.0.0.0", "255.255.255.255", 0);
- }
-
- @Test
- public void testGetImplicitNetmask() {
- assertEquals(8, getImplicitNetmask(ipv4Address("4.2.2.2")));
- assertEquals(8, getImplicitNetmask(ipv4Address("10.5.6.7")));
- assertEquals(16, getImplicitNetmask(ipv4Address("173.194.72.105")));
- assertEquals(16, getImplicitNetmask(ipv4Address("172.23.68.145")));
- assertEquals(24, getImplicitNetmask(ipv4Address("192.0.2.1")));
- assertEquals(24, getImplicitNetmask(ipv4Address("192.168.5.1")));
- assertEquals(32, getImplicitNetmask(ipv4Address("224.0.0.1")));
- assertEquals(32, getImplicitNetmask(ipv4Address("255.6.7.8")));
- }
-
- private void assertInvalidNetworkMask(Inet4Address addr) {
- try {
- netmaskToPrefixLength(addr);
- fail("Invalid netmask " + addr.getHostAddress() + " did not cause exception");
- } catch (IllegalArgumentException expected) {
- }
- }
-
- @Test
- public void testNetmaskToPrefixLength() {
- assertEquals(0, netmaskToPrefixLength(ipv4Address("0.0.0.0")));
- assertEquals(9, netmaskToPrefixLength(ipv4Address("255.128.0.0")));
- assertEquals(17, netmaskToPrefixLength(ipv4Address("255.255.128.0")));
- assertEquals(23, netmaskToPrefixLength(ipv4Address("255.255.254.0")));
- assertEquals(31, netmaskToPrefixLength(ipv4Address("255.255.255.254")));
- assertEquals(32, netmaskToPrefixLength(ipv4Address("255.255.255.255")));
-
- assertInvalidNetworkMask(ipv4Address("0.0.0.1"));
- assertInvalidNetworkMask(ipv4Address("255.255.255.253"));
- assertInvalidNetworkMask(ipv4Address("255.255.0.255"));
- }
-
- @Test
- public void testGetPrefixMaskAsAddress() {
- assertEquals("255.255.240.0", getPrefixMaskAsInet4Address(20).getHostAddress());
- assertEquals("255.0.0.0", getPrefixMaskAsInet4Address(8).getHostAddress());
- assertEquals("0.0.0.0", getPrefixMaskAsInet4Address(0).getHostAddress());
- assertEquals("255.255.255.255", getPrefixMaskAsInet4Address(32).getHostAddress());
- }
-
- @Test
- public void testGetBroadcastAddress() {
- assertEquals("192.168.15.255",
- getBroadcastAddress(ipv4Address("192.168.0.123"), 20).getHostAddress());
- assertEquals("192.255.255.255",
- getBroadcastAddress(ipv4Address("192.168.0.123"), 8).getHostAddress());
- assertEquals("192.168.0.123",
- getBroadcastAddress(ipv4Address("192.168.0.123"), 32).getHostAddress());
- assertEquals("255.255.255.255",
- getBroadcastAddress(ipv4Address("192.168.0.123"), 0).getHostAddress());
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void testGetBroadcastAddress_PrefixTooLarge() {
- getBroadcastAddress(ipv4Address("192.168.0.123"), 33);
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void testGetBroadcastAddress_NegativePrefix() {
- getBroadcastAddress(ipv4Address("192.168.0.123"), -1);
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void testGetPrefixMaskAsAddress_PrefixTooLarge() {
- getPrefixMaskAsInet4Address(33);
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void testGetPrefixMaskAsAddress_NegativePrefix() {
- getPrefixMaskAsInet4Address(-1);
- }
-
- private Inet4Address ipv4Address(String addr) {
- return (Inet4Address) InetAddresses.parseNumericAddress(addr);
- }
-}
diff --git a/tests/net/java/android/net/shared/InitialConfigurationTest.java b/tests/net/java/android/net/shared/InitialConfigurationTest.java
deleted file mode 100644
index 17f8324..0000000
--- a/tests/net/java/android/net/shared/InitialConfigurationTest.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.shared;
-
-import static android.net.InetAddresses.parseNumericAddress;
-
-import static com.android.testutils.MiscAssertsKt.assertFieldCountEquals;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotEquals;
-
-import android.net.IpPrefix;
-import android.net.LinkAddress;
-
-import androidx.test.filters.SmallTest;
-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.function.Consumer;
-
-/**
- * Tests for {@link InitialConfiguration}
- */
-@RunWith(AndroidJUnit4.class)
-@SmallTest
-public class InitialConfigurationTest {
- private InitialConfiguration mConfig;
-
- @Before
- public void setUp() {
- mConfig = new InitialConfiguration();
- mConfig.ipAddresses.addAll(Arrays.asList(
- new LinkAddress(parseNumericAddress("192.168.45.45"), 16),
- new LinkAddress(parseNumericAddress("2001:db8::45"), 33)));
- mConfig.directlyConnectedRoutes.addAll(Arrays.asList(
- new IpPrefix(parseNumericAddress("192.168.46.46"), 17),
- new IpPrefix(parseNumericAddress("2001:db8::46"), 34)));
- mConfig.dnsServers.addAll(Arrays.asList(
- parseNumericAddress("192.168.47.47"),
- parseNumericAddress("2001:db8::47")));
- // Any added InitialConfiguration field must be included in equals() to be tested properly
- assertFieldCountEquals(3, InitialConfiguration.class);
- }
-
- @Test
- public void testParcelUnparcelInitialConfiguration() {
- final InitialConfiguration unparceled =
- InitialConfiguration.fromStableParcelable(mConfig.toStableParcelable());
- assertEquals(mConfig, unparceled);
- }
-
- @Test
- public void testEquals() {
- assertEquals(mConfig, InitialConfiguration.copy(mConfig));
-
- assertNotEqualsAfterChange(c -> c.ipAddresses.add(
- new LinkAddress(parseNumericAddress("192.168.47.47"), 24)));
- assertNotEqualsAfterChange(c -> c.directlyConnectedRoutes.add(
- new IpPrefix(parseNumericAddress("192.168.46.46"), 32)));
- assertNotEqualsAfterChange(c -> c.dnsServers.add(parseNumericAddress("2001:db8::49")));
- assertFieldCountEquals(3, InitialConfiguration.class);
- }
-
- private void assertNotEqualsAfterChange(Consumer<InitialConfiguration> mutator) {
- final InitialConfiguration newConfig = InitialConfiguration.copy(mConfig);
- mutator.accept(newConfig);
- assertNotEquals(mConfig, newConfig);
- }
-}
diff --git a/tests/net/java/android/net/shared/IpConfigurationParcelableUtilTest.java b/tests/net/java/android/net/shared/IpConfigurationParcelableUtilTest.java
deleted file mode 100644
index f987389..0000000
--- a/tests/net/java/android/net/shared/IpConfigurationParcelableUtilTest.java
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.shared;
-
-import static android.net.InetAddresses.parseNumericAddress;
-import static android.net.shared.IpConfigurationParcelableUtil.fromStableParcelable;
-import static android.net.shared.IpConfigurationParcelableUtil.toStableParcelable;
-
-import static com.android.testutils.MiscAssertsKt.assertFieldCountEquals;
-
-import static org.junit.Assert.assertEquals;
-
-import android.net.DhcpResults;
-import android.net.LinkAddress;
-
-import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.net.Inet4Address;
-
-/**
- * Tests for {@link IpConfigurationParcelableUtil}.
- */
-@RunWith(AndroidJUnit4.class)
-@SmallTest
-public class IpConfigurationParcelableUtilTest {
- private DhcpResults mDhcpResults;
-
- @Before
- public void setUp() {
- mDhcpResults = new DhcpResults();
- mDhcpResults.ipAddress = new LinkAddress(parseNumericAddress("2001:db8::42"), 64);
- mDhcpResults.gateway = parseNumericAddress("192.168.42.42");
- mDhcpResults.dnsServers.add(parseNumericAddress("2001:db8::43"));
- mDhcpResults.dnsServers.add(parseNumericAddress("192.168.43.43"));
- mDhcpResults.domains = "example.com";
- mDhcpResults.serverAddress = (Inet4Address) parseNumericAddress("192.168.44.44");
- mDhcpResults.vendorInfo = "TEST_VENDOR_INFO";
- mDhcpResults.leaseDuration = 3600;
- mDhcpResults.serverHostName = "dhcp.example.com";
- mDhcpResults.mtu = 1450;
- // Any added DhcpResults field must be included in equals() to be tested properly
- assertFieldCountEquals(9, DhcpResults.class);
- }
-
- @Test
- public void testParcelUnparcelDhcpResults() {
- doDhcpResultsParcelUnparcelTest();
- }
-
- @Test
- public void testParcelUnparcelDhcpResults_NullIpAddress() {
- mDhcpResults.ipAddress = null;
- doDhcpResultsParcelUnparcelTest();
- }
-
- @Test
- public void testParcelUnparcelDhcpResults_NullGateway() {
- mDhcpResults.gateway = null;
- doDhcpResultsParcelUnparcelTest();
- }
-
- @Test
- public void testParcelUnparcelDhcpResults_NullDomains() {
- mDhcpResults.domains = null;
- doDhcpResultsParcelUnparcelTest();
- }
-
- @Test
- public void testParcelUnparcelDhcpResults_EmptyDomains() {
- mDhcpResults.domains = "";
- doDhcpResultsParcelUnparcelTest();
- }
-
- @Test
- public void testParcelUnparcelDhcpResults_NullServerAddress() {
- mDhcpResults.serverAddress = null;
- doDhcpResultsParcelUnparcelTest();
- }
-
- @Test
- public void testParcelUnparcelDhcpResults_NullVendorInfo() {
- mDhcpResults.vendorInfo = null;
- doDhcpResultsParcelUnparcelTest();
- }
-
- @Test
- public void testParcelUnparcelDhcpResults_NullServerHostName() {
- mDhcpResults.serverHostName = null;
- doDhcpResultsParcelUnparcelTest();
- }
-
- private void doDhcpResultsParcelUnparcelTest() {
- final DhcpResults unparceled = fromStableParcelable(toStableParcelable(mDhcpResults));
- assertEquals(mDhcpResults, unparceled);
- }
-}
diff --git a/tests/net/java/android/net/shared/ProvisioningConfigurationTest.java b/tests/net/java/android/net/shared/ProvisioningConfigurationTest.java
deleted file mode 100644
index 7079a28..0000000
--- a/tests/net/java/android/net/shared/ProvisioningConfigurationTest.java
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.shared;
-
-import static android.net.InetAddresses.parseNumericAddress;
-import static android.net.shared.ProvisioningConfiguration.fromStableParcelable;
-
-import static com.android.testutils.MiscAssertsKt.assertFieldCountEquals;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotEquals;
-
-import android.net.LinkAddress;
-import android.net.Network;
-import android.net.StaticIpConfiguration;
-import android.net.apf.ApfCapabilities;
-
-import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.util.function.Consumer;
-
-/**
- * Tests for {@link ProvisioningConfiguration}.
- */
-@RunWith(AndroidJUnit4.class)
-@SmallTest
-public class ProvisioningConfigurationTest {
- private ProvisioningConfiguration mConfig;
-
- @Before
- public void setUp() {
- mConfig = new ProvisioningConfiguration();
- mConfig.mEnableIPv4 = true;
- mConfig.mEnableIPv6 = true;
- mConfig.mUsingMultinetworkPolicyTracker = true;
- mConfig.mUsingIpReachabilityMonitor = true;
- mConfig.mRequestedPreDhcpActionMs = 42;
- mConfig.mInitialConfig = new InitialConfiguration();
- mConfig.mInitialConfig.ipAddresses.add(
- new LinkAddress(parseNumericAddress("192.168.42.42"), 24));
- mConfig.mStaticIpConfig = new StaticIpConfiguration();
- mConfig.mStaticIpConfig.ipAddress =
- new LinkAddress(parseNumericAddress("2001:db8::42"), 90);
- // Not testing other InitialConfig or StaticIpConfig members: they have their own unit tests
- mConfig.mApfCapabilities = new ApfCapabilities(1, 2, 3);
- mConfig.mProvisioningTimeoutMs = 4200;
- mConfig.mIPv6AddrGenMode = 123;
- mConfig.mNetwork = new Network(321);
- mConfig.mDisplayName = "test_config";
- // Any added field must be included in equals() to be tested properly
- assertFieldCountEquals(12, ProvisioningConfiguration.class);
- }
-
- @Test
- public void testParcelUnparcel() {
- doParcelUnparcelTest();
- }
-
- @Test
- public void testParcelUnparcel_NullInitialConfiguration() {
- mConfig.mInitialConfig = null;
- doParcelUnparcelTest();
- }
-
- @Test
- public void testParcelUnparcel_NullStaticConfiguration() {
- mConfig.mStaticIpConfig = null;
- doParcelUnparcelTest();
- }
-
- @Test
- public void testParcelUnparcel_NullApfCapabilities() {
- mConfig.mApfCapabilities = null;
- doParcelUnparcelTest();
- }
-
- @Test
- public void testParcelUnparcel_NullNetwork() {
- mConfig.mNetwork = null;
- doParcelUnparcelTest();
- }
-
- private void doParcelUnparcelTest() {
- final ProvisioningConfiguration unparceled =
- fromStableParcelable(mConfig.toStableParcelable());
- assertEquals(mConfig, unparceled);
- }
-
- @Test
- public void testEquals() {
- assertEquals(mConfig, new ProvisioningConfiguration(mConfig));
-
- assertNotEqualsAfterChange(c -> c.mEnableIPv4 = false);
- assertNotEqualsAfterChange(c -> c.mEnableIPv6 = false);
- assertNotEqualsAfterChange(c -> c.mUsingMultinetworkPolicyTracker = false);
- assertNotEqualsAfterChange(c -> c.mUsingIpReachabilityMonitor = false);
- assertNotEqualsAfterChange(c -> c.mRequestedPreDhcpActionMs++);
- assertNotEqualsAfterChange(c -> c.mInitialConfig.ipAddresses.add(
- new LinkAddress(parseNumericAddress("192.168.47.47"), 16)));
- assertNotEqualsAfterChange(c -> c.mInitialConfig = null);
- assertNotEqualsAfterChange(c -> c.mStaticIpConfig.ipAddress =
- new LinkAddress(parseNumericAddress("2001:db8::47"), 64));
- assertNotEqualsAfterChange(c -> c.mStaticIpConfig = null);
- assertNotEqualsAfterChange(c -> c.mApfCapabilities = new ApfCapabilities(4, 5, 6));
- assertNotEqualsAfterChange(c -> c.mApfCapabilities = null);
- assertNotEqualsAfterChange(c -> c.mProvisioningTimeoutMs++);
- assertNotEqualsAfterChange(c -> c.mIPv6AddrGenMode++);
- assertNotEqualsAfterChange(c -> c.mNetwork = new Network(123));
- assertNotEqualsAfterChange(c -> c.mNetwork = null);
- assertNotEqualsAfterChange(c -> c.mDisplayName = "other_test");
- assertNotEqualsAfterChange(c -> c.mDisplayName = null);
- assertFieldCountEquals(12, ProvisioningConfiguration.class);
- }
-
- private void assertNotEqualsAfterChange(Consumer<ProvisioningConfiguration> mutator) {
- final ProvisioningConfiguration newConfig = new ProvisioningConfiguration(mConfig);
- mutator.accept(newConfig);
- assertNotEquals(mConfig, newConfig);
- }
-}
diff --git a/tests/net/java/android/net/util/InterfaceParamsTest.java b/tests/net/java/android/net/util/InterfaceParamsTest.java
deleted file mode 100644
index 141455c..0000000
--- a/tests/net/java/android/net/util/InterfaceParamsTest.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * 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.
- */
-
-package android.net.util;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-
-import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-@RunWith(AndroidJUnit4.class)
-@SmallTest
-public class InterfaceParamsTest {
- @Test
- public void testNullInterfaceReturnsNull() {
- assertNull(InterfaceParams.getByName(null));
- }
-
- @Test
- public void testNonExistentInterfaceReturnsNull() {
- assertNull(InterfaceParams.getByName("doesnotexist0"));
- }
-
- @Test
- public void testLoopback() {
- final InterfaceParams ifParams = InterfaceParams.getByName("lo");
- assertNotNull(ifParams);
- assertEquals("lo", ifParams.name);
- assertTrue(ifParams.index > 0);
- assertNotNull(ifParams.macAddr);
- assertTrue(ifParams.defaultMtu >= NetworkConstants.ETHER_MTU);
- }
-}
diff --git a/tests/net/java/android/net/util/SharedLogTest.java b/tests/net/java/android/net/util/SharedLogTest.java
deleted file mode 100644
index e1dba36..0000000
--- a/tests/net/java/android/net/util/SharedLogTest.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * 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.
- */
-
-package android.net.util;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
-import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.io.ByteArrayOutputStream;
-import java.io.PrintWriter;
-
-@RunWith(AndroidJUnit4.class)
-@SmallTest
-public class SharedLogTest {
- private static final String TIMESTAMP_PATTERN = "\\d{2}:\\d{2}:\\d{2}";
- private static final String TIMESTAMP = "HH:MM:SS";
-
- @Test
- public void testBasicOperation() {
- final SharedLog logTop = new SharedLog("top");
- logTop.mark("first post!");
-
- final SharedLog logLevel2a = logTop.forSubComponent("twoA");
- final SharedLog logLevel2b = logTop.forSubComponent("twoB");
- logLevel2b.e("2b or not 2b");
- logLevel2b.e("No exception", null);
- logLevel2b.e("Wait, here's one", new Exception("Test"));
- logLevel2a.w("second post?");
-
- final SharedLog logLevel3 = logLevel2a.forSubComponent("three");
- logTop.log("still logging");
- logLevel3.log("3 >> 2");
- logLevel2a.mark("ok: last post");
-
- final String[] expected = {
- " - MARK first post!",
- " - [twoB] ERROR 2b or not 2b",
- " - [twoB] ERROR No exception",
- // No stacktrace in shared log, only in logcat
- " - [twoB] ERROR Wait, here's one: Test",
- " - [twoA] WARN second post?",
- " - still logging",
- " - [twoA.three] 3 >> 2",
- " - [twoA] MARK ok: last post",
- };
- // Verify the logs are all there and in the correct order.
- verifyLogLines(expected, logTop);
-
- // In fact, because they all share the same underlying LocalLog,
- // every subcomponent SharedLog's dump() is identical.
- verifyLogLines(expected, logLevel2a);
- verifyLogLines(expected, logLevel2b);
- verifyLogLines(expected, logLevel3);
- }
-
- private static void verifyLogLines(String[] expected, SharedLog log) {
- final ByteArrayOutputStream ostream = new ByteArrayOutputStream();
- final PrintWriter pw = new PrintWriter(ostream, true);
- log.dump(null, pw, null);
-
- final String dumpOutput = ostream.toString();
- assertTrue(dumpOutput != null);
- assertTrue(!"".equals(dumpOutput));
-
- final String[] lines = dumpOutput.split("\n");
- assertEquals(expected.length, lines.length);
-
- for (int i = 0; i < expected.length; i++) {
- String got = lines[i];
- String want = expected[i];
- assertTrue(String.format("'%s' did not contain '%s'", got, want), got.endsWith(want));
- assertTrue(String.format("'%s' did not contain a %s timestamp", got, TIMESTAMP),
- got.replaceFirst(TIMESTAMP_PATTERN, TIMESTAMP).contains(TIMESTAMP));
- }
- }
-}
diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl
index bbb8544..4619372 100644
--- a/wifi/java/android/net/wifi/IWifiManager.aidl
+++ b/wifi/java/android/net/wifi/IWifiManager.aidl
@@ -161,8 +161,6 @@
boolean setWifiApConfiguration(in WifiConfiguration wifiConfig, String packageName);
- void notifyUserOfApBandConversion(String packageName);
-
void enableTdls(String remoteIPAddress, boolean enable);
void enableTdlsWithMacAddress(String remoteMacAddress, boolean enable);
@@ -242,4 +240,6 @@
void registerSuggestionConnectionStatusListener(in IBinder binder, in ISuggestionConnectionStatusListener listener, int listenerIdentifier, String packageName, String featureId);
void unregisterSuggestionConnectionStatusListener(int listenerIdentifier, String packageName);
+
+ int calculateSignalLevel(int rssi);
}
diff --git a/wifi/java/android/net/wifi/RttManager.java b/wifi/java/android/net/wifi/RttManager.java
index 6a03c73..73c52ab 100644
--- a/wifi/java/android/net/wifi/RttManager.java
+++ b/wifi/java/android/net/wifi/RttManager.java
@@ -1212,7 +1212,7 @@
*
* @hide
*/
- public RttManager(Context context, WifiRttManager service) {
+ public RttManager(@NonNull Context context, @NonNull WifiRttManager service) {
mNewService = service;
mContext = context;
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index f7d2b40..90343d4 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -384,7 +384,12 @@
public void setSecurityParams(@SecurityType int securityType) {
// Clear all the bitsets.
allowedKeyManagement.clear();
+ allowedProtocols.clear();
allowedAuthAlgorithms.clear();
+ allowedPairwiseCiphers.clear();
+ allowedGroupCiphers.clear();
+ allowedGroupManagementCiphers.clear();
+ allowedSuiteBCiphers.clear();
switch (securityType) {
case SECURITY_TYPE_OPEN:
@@ -407,9 +412,6 @@
requirePMF = true;
break;
case SECURITY_TYPE_EAP_SUITE_B:
- allowedGroupCiphers.clear();
- allowedGroupManagementCiphers.clear();
- allowedSuiteBCiphers.clear();
allowedKeyManagement.set(WifiConfiguration.KeyMgmt.SUITE_B_192);
allowedGroupCiphers.set(WifiConfiguration.GroupCipher.GCMP_256);
allowedGroupManagementCiphers.set(WifiConfiguration.GroupMgmtCipher.BIP_GMAC_256);
@@ -945,12 +947,6 @@
public int meteredOverride = METERED_OVERRIDE_NONE;
/**
- * This Wifi configuration is a clone of another network with lower security
- * @hide
- */
- public String clonedNetworkConfigKey;
-
- /**
* Blend together all the various opinions to decide if the given network
* should be considered metered or not.
*
@@ -1808,7 +1804,6 @@
shared = true;
dtimInterval = 0;
mRandomizedMacAddress = MacAddress.fromString(WifiInfo.DEFAULT_MAC_ADDRESS);
- clonedNetworkConfigKey = null;
}
/**
@@ -2376,7 +2371,6 @@
/** copy constructor {@hide} */
@UnsupportedAppUsage
-
public WifiConfiguration(WifiConfiguration source) {
if (source != null) {
networkId = source.networkId;
@@ -2460,7 +2454,6 @@
requirePMF = source.requirePMF;
updateIdentifier = source.updateIdentifier;
carrierId = source.carrierId;
- clonedNetworkConfigKey = source.clonedNetworkConfigKey;
}
}
@@ -2536,7 +2529,6 @@
dest.writeInt(osu ? 1 : 0);
dest.writeLong(randomizedMacExpirationTimeMs);
dest.writeInt(carrierId);
- dest.writeString(clonedNetworkConfigKey);
}
/** Implement the Parcelable interface {@hide} */
@@ -2614,7 +2606,6 @@
config.osu = in.readInt() != 0;
config.randomizedMacExpirationTimeMs = in.readLong();
config.carrierId = in.readInt();
- config.clonedNetworkConfigKey = in.readString();
return config;
}
diff --git a/wifi/java/android/net/wifi/WifiFrameworkInitializer.java b/wifi/java/android/net/wifi/WifiFrameworkInitializer.java
new file mode 100644
index 0000000..775043a
--- /dev/null
+++ b/wifi/java/android/net/wifi/WifiFrameworkInitializer.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.net.wifi;
+
+import android.annotation.SystemApi;
+import android.app.SystemServiceRegistry;
+import android.content.Context;
+import android.net.wifi.aware.IWifiAwareManager;
+import android.net.wifi.aware.WifiAwareManager;
+import android.net.wifi.p2p.IWifiP2pManager;
+import android.net.wifi.p2p.WifiP2pManager;
+import android.net.wifi.rtt.IWifiRttManager;
+import android.net.wifi.rtt.WifiRttManager;
+import android.os.HandlerThread;
+import android.os.Looper;
+
+/**
+ * Class for performing registration for all Wifi services.
+ *
+ * @hide
+ */
+@SystemApi
+public class WifiFrameworkInitializer {
+
+ /**
+ * A class implementing the lazy holder idiom: the unique static instance
+ * of {@link #INSTANCE} is instantiated in a thread-safe way (guaranteed by
+ * the language specs) the first time that NoPreloadHolder is referenced in getInstanceLooper().
+ *
+ * This is necessary because we can't spawn a new thread in {@link #registerServiceWrappers()}.
+ * {@link #registerServiceWrappers()} is called during the Zygote phase, which disallows
+ * spawning new threads. Naming the class "NoPreloadHolder" ensures that the classloader will
+ * not preload this class, inadvertently spawning the thread too early.
+ */
+ private static class NoPreloadHolder {
+ private static final HandlerThread INSTANCE = createInstance();
+
+ private static HandlerThread createInstance() {
+ HandlerThread thread = new HandlerThread("WifiManagerThread");
+ thread.start();
+ return thread;
+ }
+ }
+
+ private static Looper getInstanceLooper() {
+ return NoPreloadHolder.INSTANCE.getLooper();
+ }
+
+ private WifiFrameworkInitializer() {}
+
+ /**
+ * Called by {@link SystemServiceRegistry}'s static initializer and registers all Wifi services
+ * to {@link Context}, so that {@link Context#getSystemService} can return them.
+ *
+ * @throws IllegalStateException if this is called from anywhere besides
+ * {@link SystemServiceRegistry}
+ */
+ public static void registerServiceWrappers() {
+ SystemServiceRegistry.registerContextAwareService(
+ Context.WIFI_SERVICE,
+ WifiManager.class,
+ context -> new WifiManager(context, getInstanceLooper())
+ );
+ SystemServiceRegistry.registerStaticService(
+ Context.WIFI_P2P_SERVICE,
+ WifiP2pManager.class,
+ serviceBinder -> {
+ IWifiP2pManager service = IWifiP2pManager.Stub.asInterface(serviceBinder);
+ return new WifiP2pManager(service);
+ }
+ );
+ SystemServiceRegistry.registerContextAwareService(
+ Context.WIFI_AWARE_SERVICE,
+ WifiAwareManager.class,
+ (context, serviceBinder) -> {
+ IWifiAwareManager service = IWifiAwareManager.Stub.asInterface(serviceBinder);
+ return new WifiAwareManager(context, service);
+ }
+ );
+ SystemServiceRegistry.registerContextAwareService(
+ Context.WIFI_SCANNING_SERVICE,
+ WifiScanner.class,
+ (context, serviceBinder) -> {
+ IWifiScanner service = IWifiScanner.Stub.asInterface(serviceBinder);
+ return new WifiScanner(context, service, getInstanceLooper());
+ }
+ );
+ SystemServiceRegistry.registerContextAwareService(
+ Context.WIFI_RTT_SERVICE,
+ RttManager.class,
+ (context, serviceBinder) -> {
+ IWifiRttManager service = IWifiRttManager.Stub.asInterface(serviceBinder);
+ WifiRttManager wifiRttManager = new WifiRttManager(context, service);
+ return new RttManager(context, wifiRttManager);
+ }
+ );
+ SystemServiceRegistry.registerContextAwareService(
+ Context.WIFI_RTT_RANGING_SERVICE,
+ WifiRttManager.class,
+ (context, serviceBinder) -> {
+ IWifiRttManager service = IWifiRttManager.Stub.asInterface(serviceBinder);
+ return new WifiRttManager(context, service);
+ }
+ );
+ }
+}
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 6c2a08c..942d795 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -1153,8 +1153,6 @@
* @hide
*/
@UnsupportedAppUsage
- // TODO(b/140781184): need to support custom number of RSSI levels, as well as levels that are
- // not evenly spaced
public static final int RSSI_LEVELS = 5;
/**
@@ -1215,11 +1213,13 @@
* Applications will almost always want to use
* {@link android.content.Context#getSystemService Context.getSystemService()} to retrieve
* the standard {@link android.content.Context#WIFI_SERVICE Context.WIFI_SERVICE}.
+ *
* @param context the application context
- * @hide - hide this because it takes in a parameter of type IWifiManager, which
- * is a system private class.
+ * @param looper the Looper used to deliver callbacks
+ *
+ * @hide
*/
- public WifiManager(Context context, Looper looper) {
+ public WifiManager(@NonNull Context context, @NonNull Looper looper) {
mContext = context;
mLooper = looper;
mTargetSdkVersion = context.getApplicationInfo().targetSdkVersion;
@@ -2782,11 +2782,13 @@
* is being shown.
*
* @param rssi The power of the signal measured in RSSI.
- * @param numLevels The number of levels to consider in the calculated
- * level.
- * @return A level of the signal, given in the range of 0 to numLevels-1
- * (both inclusive).
+ * @param numLevels The number of levels to consider in the calculated level.
+ * @return A level of the signal, given in the range of 0 to numLevels-1 (both inclusive).
+ * @deprecated Callers should use {@link #calculateSignalLevel(int)} instead to get the
+ * signal level using the system default RSSI thresholds, or otherwise compute the RSSI level
+ * themselves using their own formula.
*/
+ @Deprecated
public static int calculateSignalLevel(int rssi, int numLevels) {
if (rssi <= MIN_RSSI) {
return 0;
@@ -2800,6 +2802,34 @@
}
/**
+ * Given a raw RSSI, return the RSSI signal quality rating using the system default RSSI
+ * quality rating thresholds.
+ * @param rssi a raw RSSI value, in dBm, usually between -55 and -90
+ * @return the RSSI signal quality rating, in the range
+ * [0, {@link #getMaxSignalLevel()}], where 0 is the lowest (worst signal) RSSI
+ * rating and {@link #getMaxSignalLevel()} is the highest (best signal) RSSI rating.
+ */
+ public int calculateSignalLevel(int rssi) {
+ try {
+ IWifiManager iWifiManager = getIWifiManager();
+ if (iWifiManager == null) {
+ throw new RemoteException("Wifi service is not running");
+ }
+ return iWifiManager.calculateSignalLevel(rssi);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Get the system default maximum signal level.
+ * This is the maximum RSSI level returned by {@link #calculateSignalLevel(int)}.
+ */
+ public int getMaxSignalLevel() {
+ return calculateSignalLevel(Integer.MAX_VALUE);
+ }
+
+ /**
* Compares two signal strengths.
*
* @param rssiA The power of the first signal measured in RSSI.
@@ -3207,27 +3237,6 @@
}
/**
- * Method that triggers a notification to the user about a band conversion
- * (e.g. 5 GHz to 2.4 GHz) to their saved AP config.
- *
- * @hide
- */
- // TODO(b/144218444): move the notification to Settings instead of making this @SystemApi
- @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
- public void notifyUserOfApBandConversion() {
- Log.d(TAG, "apBand was converted, notify the user");
- try {
- IWifiManager iWifiManager = getIWifiManager();
- if (iWifiManager == null) {
- throw new RemoteException("Wifi service is not running");
- }
- iWifiManager.notifyUserOfApBandConversion(mContext.getOpPackageName());
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- /**
* Enable/Disable TDLS on a specific local route.
*
* <p>
diff --git a/wifi/java/android/net/wifi/WifiNetworkScoreCache.java b/wifi/java/android/net/wifi/WifiNetworkScoreCache.java
index b22ae070..5a212a8 100755
--- a/wifi/java/android/net/wifi/WifiNetworkScoreCache.java
+++ b/wifi/java/android/net/wifi/WifiNetworkScoreCache.java
@@ -22,6 +22,7 @@
import android.content.Context;
import android.net.INetworkScoreCache;
import android.net.NetworkKey;
+import android.net.NetworkScoreManager;
import android.net.ScoredNetwork;
import android.os.Handler;
import android.os.Process;
@@ -40,7 +41,8 @@
*
* @hide
*/
-public class WifiNetworkScoreCache extends INetworkScoreCache.Stub {
+public class WifiNetworkScoreCache extends INetworkScoreCache.Stub
+ implements NetworkScoreManager.NetworkScoreCallback {
private static final String TAG = "WifiNetworkScoreCache";
private static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG);
@@ -246,6 +248,17 @@
}
@Override protected final void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
+ WifiManager wifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
+ dumpWithLatestScanResults(fd, writer, args, wifiManager.getScanResults());
+ }
+
+ /**
+ * This is directly invoked from within Wifi-Service (on it's instance of this class), hence
+ * avoid making the WifiManager.getScanResults() call to avoid a deadlock.
+ */
+ public final void dumpWithLatestScanResults(
+ FileDescriptor fd, PrintWriter writer, String[] args,
+ List<ScanResult> latestScanResults) {
mContext.enforceCallingOrSelfPermission(permission.DUMP, TAG);
String header = String.format("WifiNetworkScoreCache (%s/%d)",
mContext.getPackageName(), Process.myUid());
@@ -256,8 +269,7 @@
writer.println(" " + score);
}
writer.println(" Network scores for latest ScanResults:");
- WifiManager wifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
- for (ScanResult scanResult : wifiManager.getScanResults()) {
+ for (ScanResult scanResult : latestScanResults) {
writer.println(
" " + buildNetworkKey(scanResult) + ": " + getNetworkScore(scanResult));
}
diff --git a/wifi/java/android/net/wifi/WifiScanner.java b/wifi/java/android/net/wifi/WifiScanner.java
index 0d36718..0de5066 100644
--- a/wifi/java/android/net/wifi/WifiScanner.java
+++ b/wifi/java/android/net/wifi/WifiScanner.java
@@ -789,12 +789,11 @@
/**
* Enable/Disable wifi scanning.
- * Note: WifiService calls this after any client interface mode changes (i.e. a new interface
- * set up or an existing interface torn down)
- * If there are >= 1 active client interface, invoke setScanningEnabled(true)
- * If there are 0 active client interface, invoke setScanningEnabled(false)
+ *
+ * @param enable set to true to enable scanning, set to false to disable all types of scanning.
* {@hide}
*/
+ @SystemApi
@RequiresPermission(Manifest.permission.NETWORK_STACK)
public void setScanningEnabled(boolean enable) {
validateChannel();
@@ -1291,12 +1290,15 @@
* Applications will almost always want to use
* {@link android.content.Context#getSystemService Context.getSystemService()} to retrieve
* the standard {@link android.content.Context#WIFI_SERVICE Context.WIFI_SERVICE}.
+ *
* @param context the application context
- * @param service the Binder interface
+ * @param service the Binder interface for {@link Context#WIFI_SCANNING_SERVICE}
* @param looper the Looper used to deliver callbacks
+ *
* @hide
*/
- public WifiScanner(Context context, IWifiScanner service, Looper looper) {
+ public WifiScanner(@NonNull Context context, @NonNull IWifiScanner service,
+ @NonNull Looper looper) {
mContext = context;
mService = service;
diff --git a/wifi/java/android/net/wifi/aware/WifiAwareManager.java b/wifi/java/android/net/wifi/aware/WifiAwareManager.java
index 5aab347..7b37d65 100644
--- a/wifi/java/android/net/wifi/aware/WifiAwareManager.java
+++ b/wifi/java/android/net/wifi/aware/WifiAwareManager.java
@@ -158,7 +158,7 @@
private final Object mLock = new Object(); // lock access to the following vars
/** @hide */
- public WifiAwareManager(Context context, IWifiAwareManager service) {
+ public WifiAwareManager(@NonNull Context context, @NonNull IWifiAwareManager service) {
mContext = context;
mService = service;
}
diff --git a/wifi/java/android/net/wifi/rtt/WifiRttManager.java b/wifi/java/android/net/wifi/rtt/WifiRttManager.java
index 770a120..cb0c5d4 100644
--- a/wifi/java/android/net/wifi/rtt/WifiRttManager.java
+++ b/wifi/java/android/net/wifi/rtt/WifiRttManager.java
@@ -77,7 +77,7 @@
"android.net.wifi.rtt.action.WIFI_RTT_STATE_CHANGED";
/** @hide */
- public WifiRttManager(Context context, IWifiRttManager service) {
+ public WifiRttManager(@NonNull Context context, @NonNull IWifiRttManager service) {
mContext = context;
mService = service;
}
diff --git a/wifi/java/com/android/server/wifi/BaseWifiService.java b/wifi/java/com/android/server/wifi/BaseWifiService.java
index cf74ff0..ee03c11 100644
--- a/wifi/java/com/android/server/wifi/BaseWifiService.java
+++ b/wifi/java/com/android/server/wifi/BaseWifiService.java
@@ -42,7 +42,6 @@
import android.net.wifi.hotspot2.OsuProvider;
import android.net.wifi.hotspot2.PasspointConfiguration;
import android.os.IBinder;
-import android.os.Messenger;
import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.WorkSource;
@@ -325,7 +324,6 @@
throw new UnsupportedOperationException();
}
- @Override
public void notifyUserOfApBandConversion(String packageName) {
throw new UnsupportedOperationException();
}
@@ -537,4 +535,9 @@
String packageName) {
throw new UnsupportedOperationException();
}
+
+ @Override
+ public int calculateSignalLevel(int rssi) {
+ throw new UnsupportedOperationException();
+ }
}
diff --git a/wifi/tests/src/android/net/wifi/WifiManagerTest.java b/wifi/tests/src/android/net/wifi/WifiManagerTest.java
index 06ebc1b..507d502 100644
--- a/wifi/tests/src/android/net/wifi/WifiManagerTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiManagerTest.java
@@ -1899,8 +1899,25 @@
*/
@Test
public void testRemoveSuggestionConnectionListener() throws Exception {
-
mWifiManager.removeSuggestionConnectionStatusListener(mListener);
verify(mWifiService).unregisterSuggestionConnectionStatusListener(anyInt(), anyString());
}
+
+ /** Test {@link WifiManager#calculateSignalLevel(int)} */
+ @Test
+ public void testCalculateSignalLevel() throws Exception {
+ when(mWifiService.calculateSignalLevel(anyInt())).thenReturn(3);
+ int actual = mWifiManager.calculateSignalLevel(-60);
+ verify(mWifiService).calculateSignalLevel(-60);
+ assertEquals(3, actual);
+ }
+
+ /** Test {@link WifiManager#getMaxSignalLevel()} */
+ @Test
+ public void testGetMaxSignalLevel() throws Exception {
+ when(mWifiService.calculateSignalLevel(anyInt())).thenReturn(4);
+ int actual = mWifiManager.getMaxSignalLevel();
+ verify(mWifiService).calculateSignalLevel(Integer.MAX_VALUE);
+ assertEquals(4, actual);
+ }
}