Merge "statsd: fix -Wreorder-init-list"
diff --git a/Android.bp b/Android.bp
index ea14b9d..180e1d3 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",
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..2821fbe
--- /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: "appsearch-service",
+ 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/api/current.txt b/api/current.txt
index a45583a..f899e40 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -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
@@ -45590,6 +45591,8 @@
field public static final int PHONE_TYPE_NONE = 0; // 0x0
field public static final int PHONE_TYPE_SIP = 3; // 0x3
field public static final int SET_OPPORTUNISTIC_SUB_INACTIVE_SUBSCRIPTION = 2; // 0x2
+ field public static final int SET_OPPORTUNISTIC_SUB_NO_OPPORTUNISTIC_SUB_AVAILABLE = 3; // 0x3
+ field public static final int SET_OPPORTUNISTIC_SUB_REMOTE_SERVICE_EXCEPTION = 4; // 0x4
field public static final int SET_OPPORTUNISTIC_SUB_SUCCESS = 0; // 0x0
field public static final int SET_OPPORTUNISTIC_SUB_VALIDATION_FAILED = 1; // 0x1
field public static final int SIM_STATE_ABSENT = 1; // 0x1
@@ -45606,8 +45609,14 @@
field public static final int UNKNOWN_CARRIER_ID = -1; // 0xffffffff
field public static final int UNSUPPORTED_CARD_ID = -1; // 0xffffffff
field public static final int UPDATE_AVAILABLE_NETWORKS_ABORTED = 2; // 0x2
+ field public static final int UPDATE_AVAILABLE_NETWORKS_DISABLE_MODEM_FAIL = 5; // 0x5
+ field public static final int UPDATE_AVAILABLE_NETWORKS_ENABLE_MODEM_FAIL = 6; // 0x6
field public static final int UPDATE_AVAILABLE_NETWORKS_INVALID_ARGUMENTS = 3; // 0x3
+ field public static final int UPDATE_AVAILABLE_NETWORKS_MULTIPLE_NETWORKS_NOT_SUPPORTED = 7; // 0x7
field public static final int UPDATE_AVAILABLE_NETWORKS_NO_CARRIER_PRIVILEGE = 4; // 0x4
+ field public static final int UPDATE_AVAILABLE_NETWORKS_NO_OPPORTUNISTIC_SUB_AVAILABLE = 8; // 0x8
+ field public static final int UPDATE_AVAILABLE_NETWORKS_REMOTE_SERVICE_EXCEPTION = 9; // 0x9
+ field public static final int UPDATE_AVAILABLE_NETWORKS_SERVICE_IS_DISABLED = 10; // 0xa
field public static final int UPDATE_AVAILABLE_NETWORKS_SUCCESS = 0; // 0x0
field public static final int UPDATE_AVAILABLE_NETWORKS_UNKNOWN_FAILURE = 1; // 0x1
field public static final int USSD_ERROR_SERVICE_UNAVAIL = -2; // 0xfffffffe
diff --git a/api/system-current.txt b/api/system-current.txt
index e40fd24..f74b743 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -5899,7 +5899,15 @@
}
public class WorkSource implements android.os.Parcelable {
+ ctor public WorkSource(int);
+ ctor public WorkSource(int, @NonNull String);
method public android.os.WorkSource.WorkChain createWorkChain();
+ method @Nullable public String getPackageName(int);
+ method public int getUid(int);
+ method @Nullable public java.util.List<android.os.WorkSource.WorkChain> getWorkChains();
+ method public boolean isEmpty();
+ method public int size();
+ method @NonNull public android.os.WorkSource withoutNames();
}
public static final class WorkSource.WorkChain implements android.os.Parcelable {
@@ -8655,6 +8663,10 @@
method @Deprecated public static android.telephony.SubscriptionPlan.Builder createRecurringWeekly(java.time.ZonedDateTime);
}
+ public class TelephonyFrameworkInitializer {
+ method public static void registerServiceWrappers();
+ }
+
public final class TelephonyHistogram implements android.os.Parcelable {
ctor public TelephonyHistogram(int, int, int);
ctor public TelephonyHistogram(android.telephony.TelephonyHistogram);
diff --git a/api/test-current.txt b/api/test-current.txt
index 897e825..95b0cae 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -2185,10 +2185,12 @@
method public boolean add(int);
method public boolean add(int, String);
method @Deprecated public android.os.WorkSource addReturningNewbs(android.os.WorkSource);
- method public int get(int);
- method public String getName(int);
+ method @Nullable public String getPackageName(int);
+ method public int getUid(int);
+ method public boolean isEmpty();
method @Deprecated public android.os.WorkSource[] setReturningDiffs(android.os.WorkSource);
method public int size();
+ method @NonNull public android.os.WorkSource withoutNames();
}
}
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/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index d0ba879..5effa1b 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;
@@ -166,12 +167,8 @@
import android.service.persistentdata.PersistentDataBlockManager;
import android.service.vr.IVrManager;
import android.telecom.TelecomManager;
-import android.telephony.CarrierConfigManager;
-import android.telephony.SubscriptionManager;
-import android.telephony.TelephonyManager;
+import android.telephony.TelephonyFrameworkInitializer;
import android.telephony.TelephonyRegistryManager;
-import android.telephony.euicc.EuiccCardManager;
-import android.telephony.euicc.EuiccManager;
import android.util.ArrayMap;
import android.util.Log;
import android.view.ContextThemeWrapper;
@@ -604,13 +601,6 @@
return new SystemUpdateManager(service);
}});
- registerService(Context.TELEPHONY_SERVICE, TelephonyManager.class,
- new CachedServiceFetcher<TelephonyManager>() {
- @Override
- public TelephonyManager createService(ContextImpl ctx) {
- return new TelephonyManager(ctx.getOuterContext());
- }});
-
registerService(Context.TELEPHONY_REGISTRY_SERVICE, TelephonyRegistryManager.class,
new CachedServiceFetcher<TelephonyRegistryManager>() {
@Override
@@ -618,20 +608,6 @@
return new TelephonyRegistryManager(ctx);
}});
- registerService(Context.TELEPHONY_SUBSCRIPTION_SERVICE, SubscriptionManager.class,
- new CachedServiceFetcher<SubscriptionManager>() {
- @Override
- public SubscriptionManager createService(ContextImpl ctx) throws ServiceNotFoundException {
- return new SubscriptionManager(ctx.getOuterContext());
- }});
-
- registerService(Context.CARRIER_CONFIG_SERVICE, CarrierConfigManager.class,
- new CachedServiceFetcher<CarrierConfigManager>() {
- @Override
- public CarrierConfigManager createService(ContextImpl ctx) {
- return new CarrierConfigManager(ctx.getOuterContext());
- }});
-
registerService(Context.TELECOM_SERVICE, TelecomManager.class,
new CachedServiceFetcher<TelecomManager>() {
@Override
@@ -639,20 +615,6 @@
return new TelecomManager(ctx.getOuterContext());
}});
- registerService(Context.EUICC_SERVICE, EuiccManager.class,
- new CachedServiceFetcher<EuiccManager>() {
- @Override
- public EuiccManager createService(ContextImpl ctx) {
- return new EuiccManager(ctx.getOuterContext());
- }});
-
- registerService(Context.EUICC_CARD_SERVICE, EuiccCardManager.class,
- new CachedServiceFetcher<EuiccCardManager>() {
- @Override
- public EuiccCardManager createService(ContextImpl ctx) {
- return new EuiccCardManager(ctx.getOuterContext());
- }});
-
registerService(Context.UI_MODE_SERVICE, UiModeManager.class,
new CachedServiceFetcher<UiModeManager>() {
@Override
@@ -1301,6 +1263,8 @@
JobSchedulerFrameworkInitializer.registerServiceWrappers();
BlobStoreManagerFrameworkInitializer.initialize();
+ TelephonyFrameworkInitializer.registerServiceWrappers();
+ AppSearchManagerFrameworkInitializer.initialize();
} 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/content/Context.java b/core/java/android/content/Context.java
index 7703e08..8507316 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -4898,6 +4898,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/om/OverlayableInfo.java b/core/java/android/content/om/OverlayableInfo.java
new file mode 100644
index 0000000..5923907
--- /dev/null
+++ b/core/java/android/content/om/OverlayableInfo.java
@@ -0,0 +1,120 @@
+/*
+ * 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.content.om;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
+import com.android.internal.util.DataClass;
+
+import java.util.Objects;
+
+/**
+ * Immutable info on an overlayable defined inside a target package.
+ *
+ * @hide
+ */
+@DataClass(genSetters = false, genEqualsHashCode = true, genHiddenConstructor = true)
+public final class OverlayableInfo {
+
+ /**
+ * The "name" attribute of the overlayable tag. Used to identify the set of resources overlaid.
+ */
+ @NonNull
+ public final String name;
+
+ /**
+ * The "actor" attribute of the overlayable tag. Used to signal which apps are allowed to
+ * modify overlay state for this overlayable.
+ */
+ @Nullable
+ public final String actor;
+
+ // CHECKSTYLE:OFF Generated code
+ //
+
+
+
+ // Code below generated by codegen v1.0.3.
+ //
+ // DO NOT MODIFY!
+ // CHECKSTYLE:OFF Generated code
+ //
+ // To regenerate run:
+ // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/content/om/OverlayableInfo.java
+
+
+ /**
+ * Creates a new OverlayableInfo.
+ *
+ * @param name
+ * The "name" attribute of the overlayable tag. Used to identify the set of resources overlaid.
+ * @param actor
+ * The "actor" attribute of the overlayable tag. Used to signal which apps are allowed to
+ * modify overlay state for this overlayable.
+ * @hide
+ */
+ @DataClass.Generated.Member
+ public OverlayableInfo(
+ @NonNull String name,
+ @Nullable String actor) {
+ this.name = name;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, name);
+ this.actor = actor;
+
+ // onConstructed(); // You can define this method to get a callback
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public boolean equals(Object o) {
+ // You can override field equality logic by defining either of the methods like:
+ // boolean fieldNameEquals(OverlayableInfo other) { ... }
+ // boolean fieldNameEquals(FieldType otherValue) { ... }
+
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ @SuppressWarnings("unchecked")
+ OverlayableInfo that = (OverlayableInfo) o;
+ //noinspection PointlessBooleanExpression
+ return true
+ && Objects.equals(name, that.name)
+ && Objects.equals(actor, that.actor);
+ }
+
+ @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 + Objects.hashCode(name);
+ _hash = 31 * _hash + Objects.hashCode(actor);
+ return _hash;
+ }
+
+ @DataClass.Generated(
+ time = 1570059850579L,
+ codegenVersion = "1.0.3",
+ sourceFile = "frameworks/base/core/java/android/content/om/OverlayableInfo.java",
+ inputSignatures = "public final @android.annotation.NonNull java.lang.String name\npublic final @android.annotation.Nullable java.lang.String actor\nclass OverlayableInfo extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genSetters=false, genEqualsHashCode=true, genHiddenConstructor=true)")
+ @Deprecated
+ private void __metadata() {}
+
+}
diff --git a/core/java/android/content/res/ApkAssets.java b/core/java/android/content/res/ApkAssets.java
index de1d514..ad37555 100644
--- a/core/java/android/content/res/ApkAssets.java
+++ b/core/java/android/content/res/ApkAssets.java
@@ -18,6 +18,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UnsupportedAppUsage;
+import android.content.om.OverlayableInfo;
import android.content.res.loader.ResourcesProvider;
import android.text.TextUtils;
@@ -254,6 +255,17 @@
}
}
+ /** @hide */
+ @Nullable
+ public OverlayableInfo getOverlayableInfo(String overlayableName) throws IOException {
+ return nativeGetOverlayableInfo(mNativePtr, overlayableName);
+ }
+
+ /** @hide */
+ public boolean definesOverlayable() throws IOException {
+ return nativeDefinesOverlayable(mNativePtr);
+ }
+
/**
* Returns false if the underlying APK was changed since this ApkAssets was loaded.
*/
@@ -305,4 +317,7 @@
private static native long nativeGetStringBlock(long ptr);
private static native boolean nativeIsUpToDate(long ptr);
private static native long nativeOpenXml(long ptr, @NonNull String fileName) throws IOException;
+ private static native @Nullable OverlayableInfo nativeGetOverlayableInfo(long ptr,
+ String overlayableName) throws IOException;
+ private static native boolean nativeDefinesOverlayable(long ptr) throws IOException;
}
diff --git a/core/java/android/os/StatsLogEventWrapper.java b/core/java/android/os/StatsLogEventWrapper.java
index 89c9bb2..320fc13 100644
--- a/core/java/android/os/StatsLogEventWrapper.java
+++ b/core/java/android/os/StatsLogEventWrapper.java
@@ -139,7 +139,7 @@
out.writeLong(mElapsedTimeNs);
out.writeLong(mWallClockTimeNs);
if (mWorkSource != null) {
- ArrayList<android.os.WorkSource.WorkChain> workChains = mWorkSource.getWorkChains();
+ List<WorkSource.WorkChain> workChains = mWorkSource.getWorkChains();
// number of chains
out.writeInt(workChains.size());
for (int i = 0; i < workChains.size(); i++) {
diff --git a/core/java/android/os/WorkSource.java b/core/java/android/os/WorkSource.java
index 825fc64..b5635a4 100644
--- a/core/java/android/os/WorkSource.java
+++ b/core/java/android/os/WorkSource.java
@@ -13,13 +13,15 @@
import android.util.proto.ProtoOutputStream;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.Preconditions;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.List;
/**
* Describes the source of some work that may be done by someone else.
- * Currently the public representation of what a work source is is not
+ * Currently the public representation of what a work source is not
* defined; this is an opaque container.
*/
public class WorkSource implements Parcelable {
@@ -48,7 +50,7 @@
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
static WorkSource sNewbWork;
/**
- * For returning gone work form a modification operation.
+ * For returning gone work from a modification operation.
*/
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
static WorkSource sGoneWork;
@@ -91,9 +93,14 @@
}
}
- /** @hide */
- @UnsupportedAppUsage
+
+ /**
+ * Creates a work source with the given uid.
+ * @param uid the uid performing the work
+ * @hide
+ */
@TestApi
+ @SystemApi
public WorkSource(int uid) {
mNum = 1;
mUids = new int[] { uid, 0 };
@@ -101,14 +108,18 @@
mChains = null;
}
- /** @hide */
- public WorkSource(int uid, String name) {
- if (name == null) {
- throw new NullPointerException("Name can't be null");
- }
+ /**
+ * Creates a work source with the given uid and package name.
+ * @param uid the uid performing the work
+ * @param packageName the package performing the work
+ * @hide
+ */
+ @SystemApi
+ public WorkSource(int uid, @NonNull String packageName) {
+ Preconditions.checkNotNull(packageName, "packageName can't be null");
mNum = 1;
mUids = new int[] { uid, 0 };
- mNames = new String[] { name, null };
+ mNames = new String[] { packageName, null };
mChains = null;
}
@@ -138,17 +149,34 @@
Global.CHAINED_BATTERY_ATTRIBUTION_ENABLED, 0) == 1;
}
- /** @hide */
- @UnsupportedAppUsage
+ /**
+ * Returns the size of this work source.
+ * @hide
+ */
@TestApi
+ @SystemApi
public int size() {
return mNum;
}
- /** @hide */
+ /**
+ * @deprecated use {{@link #getUid(int)}} instead.
+ * @hide
+ */
@UnsupportedAppUsage
- @TestApi
+ @Deprecated
public int get(int index) {
+ return getUid(index);
+ }
+
+ /**
+ * Get the uid at the given index.
+ * If {@code index} < 0 or {@code index} >= {@link #size() N}, then the behavior is undefined.
+ * @hide
+ */
+ @TestApi
+ @SystemApi
+ public int getUid(int index) {
return mUids[index];
}
@@ -167,10 +195,25 @@
return mNum > 0 ? mUids[0] : mChains.get(0).getAttributionUid();
}
- /** @hide */
+ /**
+ * @deprecated use {{@link #getPackageName(int)}} instead.
+ * @hide
+ */
@UnsupportedAppUsage
- @TestApi
+ @Deprecated
public String getName(int index) {
+ return getPackageName(index);
+ }
+
+ /**
+ * Get the package name at the given index.
+ * If {@code index} < 0 or {@code index} >= {@link #size() N}, then the behavior is undefined.
+ * @hide
+ */
+ @TestApi
+ @SystemApi
+ @Nullable
+ public String getPackageName(int index) {
return mNames != null ? mNames[index] : null;
}
@@ -179,9 +222,8 @@
* intact.
*
* <p>Useful when combining with another WorkSource that doesn't have names.
- * @hide
*/
- public void clearNames() {
+ private void clearNames() {
if (mNames != null) {
mNames = null;
// Clear out any duplicate uids now that we don't have names to disambiguate them.
@@ -407,6 +449,22 @@
}
/**
+ * Returns a copy of this work source without any package names.
+ * If any {@link WorkChain WorkChains} are present, they are left intact.
+ *
+ * @return a {@link WorkSource} without any package names.
+ * @hide
+ */
+ @SystemApi
+ @TestApi
+ @NonNull
+ public WorkSource withoutNames() {
+ final WorkSource copy = new WorkSource(this);
+ copy.clearNames();
+ return copy;
+ }
+
+ /**
* Legacy API: DO NOT USE. Only in use from unit tests.
*
* @hide
@@ -524,6 +582,8 @@
*
* @hide for internal use only.
*/
+ @SystemApi
+ @TestApi
public boolean isEmpty() {
return mNum == 0 && (mChains == null || mChains.isEmpty());
}
@@ -532,7 +592,9 @@
* @return the list of {@code WorkChains} associated with this {@code WorkSource}.
* @hide
*/
- public ArrayList<WorkChain> getWorkChains() {
+ @SystemApi
+ @Nullable
+ public List<WorkChain> getWorkChains() {
return mChains;
}
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index 3251127..6458737 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -199,6 +199,8 @@
private static native void nativeWriteTransactionToParcel(long nativeObject, Parcel out);
private static native void nativeSetShadowRadius(long transactionObj, long nativeObject,
float shadowRadius);
+ private static native void nativeSetGlobalShadowSettings(@Size(4) float[] ambientColor,
+ @Size(4) float[] spotColor, float lightPosY, float lightPosZ, float lightRadius);
private final CloseGuard mCloseGuard = CloseGuard.get();
private String mName;
@@ -1979,6 +1981,42 @@
return sc;
}
+ private static void validateColorArg(@Size(4) float[] color) {
+ final String msg = "Color must be specified as a float array with"
+ + " four values to represent r, g, b, a in range [0..1]";
+ if (color.length != 4) {
+ throw new IllegalArgumentException(msg);
+ }
+ for (float c:color) {
+ if ((c < 0.f) || (c > 1.f)) {
+ throw new IllegalArgumentException(msg);
+ }
+ }
+ }
+
+ /**
+ * Sets the global configuration for all the shadows drawn by SurfaceFlinger. Shadow follows
+ * material design guidelines.
+ *
+ * @param ambientColor Color applied to the ambient shadow. The alpha is premultiplied. A
+ * float array with four values to represent r, g, b, a in range [0..1]
+ * @param spotColor Color applied to the spot shadow. The alpha is premultiplied. The position
+ * of the spot shadow depends on the light position. A float array with
+ * four values to represent r, g, b, a in range [0..1]
+ * @param lightPosY Y axis position of the light used to cast the spot shadow in pixels.
+ * @param lightPosZ Z axis position of the light used to cast the spot shadow in pixels. The X
+ * axis position is set to the display width / 2.
+ * @param lightRadius Radius of the light casting the shadow in pixels.
+ *[
+ * @hide
+ */
+ public static void setGlobalShadowSettings(@Size(4) float[] ambientColor,
+ @Size(4) float[] spotColor, float lightPosY, float lightPosZ, float lightRadius) {
+ validateColorArg(ambientColor);
+ validateColorArg(spotColor);
+ nativeSetGlobalShadowSettings(ambientColor, spotColor, lightPosY, lightPosZ, lightRadius);
+ }
+
/**
* An atomic set of changes to a set of SurfaceControl.
*/
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index f5bfe5c..75a5804 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -4086,7 +4086,7 @@
if (workSource != null) {
for (int i = 0; i < workSource.size(); ++i) {
- uid = mapUid(workSource.get(i));
+ uid = mapUid(workSource.getUid(i));
if (mActiveEvents.updateState(historyItem, name, uid, 0)) {
addHistoryEventLocked(elapsedRealtime, uptime, historyItem, name, uid);
}
@@ -4114,8 +4114,8 @@
String tag) {
if (workSource != null) {
for (int i = 0; i < workSource.size(); ++i) {
- uid = workSource.get(i);
- final String workSourceName = workSource.getName(i);
+ uid = workSource.getUid(i);
+ final String workSourceName = workSource.getPackageName(i);
if (isOnBattery()) {
BatteryStatsImpl.Uid.Pkg pkg = getPackageStatsLocked(uid,
@@ -4124,7 +4124,7 @@
}
}
- ArrayList<WorkChain> workChains = workSource.getWorkChains();
+ List<WorkChain> workChains = workSource.getWorkChains();
if (workChains != null) {
for (int i = 0; i < workChains.size(); ++i) {
final WorkChain wc = workChains.get(i);
@@ -4350,7 +4350,7 @@
final long uptime = mClocks.uptimeMillis();
final int N = ws.size();
for (int i=0; i<N; i++) {
- noteStartWakeLocked(ws.get(i), pid, null, name, historyName, type,
+ noteStartWakeLocked(ws.getUid(i), pid, null, name, historyName, type,
unimportantForLogging, elapsedRealtime, uptime);
}
@@ -4379,7 +4379,7 @@
// First the starts :
final int NN = newWs.size();
for (int i=0; i<NN; i++) {
- noteStartWakeLocked(newWs.get(i), newPid, null, newName, newHistoryName, newType,
+ noteStartWakeLocked(newWs.getUid(i), newPid, null, newName, newHistoryName, newType,
newUnimportantForLogging, elapsedRealtime, uptime);
}
if (wcs != null) {
@@ -4397,7 +4397,7 @@
// Then the stops :
final int NO = ws.size();
for (int i=0; i<NO; i++) {
- noteStopWakeLocked(ws.get(i), pid, null, name, historyName, type, elapsedRealtime,
+ noteStopWakeLocked(ws.getUid(i), pid, null, name, historyName, type, elapsedRealtime,
uptime);
}
if (wcs != null) {
@@ -4418,7 +4418,7 @@
final long uptime = mClocks.uptimeMillis();
final int N = ws.size();
for (int i=0; i<N; i++) {
- noteStopWakeLocked(ws.get(i), pid, null, name, historyName, type, elapsedRealtime,
+ noteStopWakeLocked(ws.getUid(i), pid, null, name, historyName, type, elapsedRealtime,
uptime);
}
@@ -4441,11 +4441,11 @@
WorkSource workSource) {
final int N = workSource.size();
for (int i = 0; i < N; ++i) {
- final int uid = mapUid(workSource.get(i));
+ final int uid = mapUid(workSource.getUid(i));
noteLongPartialWakeLockStartInternal(name, historyName, uid);
}
- final ArrayList<WorkChain> workChains = workSource.getWorkChains();
+ final List<WorkChain> workChains = workSource.getWorkChains();
if (workChains != null) {
for (int i = 0; i < workChains.size(); ++i) {
final WorkChain workChain = workChains.get(i);
@@ -4478,11 +4478,11 @@
WorkSource workSource) {
final int N = workSource.size();
for (int i = 0; i < N; ++i) {
- final int uid = mapUid(workSource.get(i));
+ final int uid = mapUid(workSource.getUid(i));
noteLongPartialWakeLockFinishInternal(name, historyName, uid);
}
- final ArrayList<WorkChain> workChains = workSource.getWorkChains();
+ final List<WorkChain> workChains = workSource.getWorkChains();
if (workChains != null) {
for (int i = 0; i < workChains.size(); ++i) {
final WorkChain workChain = workChains.get(i);
@@ -4615,11 +4615,11 @@
public void noteGpsChangedLocked(WorkSource oldWs, WorkSource newWs) {
for (int i = 0; i < newWs.size(); ++i) {
- noteStartGpsLocked(newWs.get(i), null);
+ noteStartGpsLocked(newWs.getUid(i), null);
}
for (int i = 0; i < oldWs.size(); ++i) {
- noteStopGpsLocked((oldWs.get(i)), null);
+ noteStopGpsLocked((oldWs.getUid(i)), null);
}
List<WorkChain>[] wcs = WorkSource.diffChains(oldWs, newWs);
@@ -5564,7 +5564,7 @@
public void noteBluetoothScanStartedFromSourceLocked(WorkSource ws, boolean isUnoptimized) {
final int N = ws.size();
for (int i = 0; i < N; i++) {
- noteBluetoothScanStartedLocked(null, ws.get(i), isUnoptimized);
+ noteBluetoothScanStartedLocked(null, ws.getUid(i), isUnoptimized);
}
final List<WorkChain> workChains = ws.getWorkChains();
@@ -5602,7 +5602,7 @@
public void noteBluetoothScanStoppedFromSourceLocked(WorkSource ws, boolean isUnoptimized) {
final int N = ws.size();
for (int i = 0; i < N; i++) {
- noteBluetoothScanStoppedLocked(null, ws.get(i), isUnoptimized);
+ noteBluetoothScanStoppedLocked(null, ws.getUid(i), isUnoptimized);
}
final List<WorkChain> workChains = ws.getWorkChains();
@@ -5633,7 +5633,7 @@
public void noteBluetoothScanResultsFromSourceLocked(WorkSource ws, int numNewResults) {
final int N = ws.size();
for (int i = 0; i < N; i++) {
- int uid = mapUid(ws.get(i));
+ int uid = mapUid(ws.getUid(i));
getUidStatsLocked(uid).noteBluetoothScanResultsLocked(numNewResults);
}
@@ -5692,7 +5692,7 @@
mGlobalWifiRunningTimer.startRunningLocked(elapsedRealtime);
int N = ws.size();
for (int i=0; i<N; i++) {
- int uid = mapUid(ws.get(i));
+ int uid = mapUid(ws.getUid(i));
getUidStatsLocked(uid).noteWifiRunningLocked(elapsedRealtime);
}
@@ -5715,7 +5715,7 @@
final long elapsedRealtime = mClocks.elapsedRealtime();
int N = oldWs.size();
for (int i=0; i<N; i++) {
- int uid = mapUid(oldWs.get(i));
+ int uid = mapUid(oldWs.getUid(i));
getUidStatsLocked(uid).noteWifiStoppedLocked(elapsedRealtime);
}
@@ -5729,7 +5729,7 @@
N = newWs.size();
for (int i=0; i<N; i++) {
- int uid = mapUid(newWs.get(i));
+ int uid = mapUid(newWs.getUid(i));
getUidStatsLocked(uid).noteWifiRunningLocked(elapsedRealtime);
}
@@ -5757,7 +5757,7 @@
mGlobalWifiRunningTimer.stopRunningLocked(elapsedRealtime);
int N = ws.size();
for (int i=0; i<N; i++) {
- int uid = mapUid(ws.get(i));
+ int uid = mapUid(ws.getUid(i));
getUidStatsLocked(uid).noteWifiStoppedLocked(elapsedRealtime);
}
@@ -5963,7 +5963,7 @@
public void noteFullWifiLockAcquiredFromSourceLocked(WorkSource ws) {
int N = ws.size();
for (int i=0; i<N; i++) {
- final int uid = mapUid(ws.get(i));
+ final int uid = mapUid(ws.getUid(i));
noteFullWifiLockAcquiredLocked(uid);
}
@@ -5980,7 +5980,7 @@
public void noteFullWifiLockReleasedFromSourceLocked(WorkSource ws) {
int N = ws.size();
for (int i=0; i<N; i++) {
- final int uid = mapUid(ws.get(i));
+ final int uid = mapUid(ws.getUid(i));
noteFullWifiLockReleasedLocked(uid);
}
@@ -5997,7 +5997,7 @@
public void noteWifiScanStartedFromSourceLocked(WorkSource ws) {
int N = ws.size();
for (int i=0; i<N; i++) {
- final int uid = mapUid(ws.get(i));
+ final int uid = mapUid(ws.getUid(i));
noteWifiScanStartedLocked(uid);
}
@@ -6014,7 +6014,7 @@
public void noteWifiScanStoppedFromSourceLocked(WorkSource ws) {
int N = ws.size();
for (int i=0; i<N; i++) {
- final int uid = mapUid(ws.get(i));
+ final int uid = mapUid(ws.getUid(i));
noteWifiScanStoppedLocked(uid);
}
@@ -6031,7 +6031,7 @@
public void noteWifiBatchedScanStartedFromSourceLocked(WorkSource ws, int csph) {
int N = ws.size();
for (int i=0; i<N; i++) {
- noteWifiBatchedScanStartedLocked(ws.get(i), csph);
+ noteWifiBatchedScanStartedLocked(ws.getUid(i), csph);
}
final List<WorkChain> workChains = ws.getWorkChains();
@@ -6045,7 +6045,7 @@
public void noteWifiBatchedScanStoppedFromSourceLocked(WorkSource ws) {
int N = ws.size();
for (int i=0; i<N; i++) {
- noteWifiBatchedScanStoppedLocked(ws.get(i));
+ noteWifiBatchedScanStoppedLocked(ws.getUid(i));
}
final List<WorkChain> workChains = ws.getWorkChains();
diff --git a/core/java/com/android/server/SystemConfig.java b/core/java/com/android/server/SystemConfig.java
index ed7f5de..49a73ee 100644
--- a/core/java/com/android/server/SystemConfig.java
+++ b/core/java/com/android/server/SystemConfig.java
@@ -18,6 +18,7 @@
import static com.android.internal.util.ArrayUtils.appendInt;
+import android.annotation.NonNull;
import android.app.ActivityManager;
import android.content.ComponentName;
import android.content.pm.FeatureInfo;
@@ -221,6 +222,12 @@
private ArrayMap<String, Set<String>> mPackageToUserTypeWhitelist = new ArrayMap<>();
private ArrayMap<String, Set<String>> mPackageToUserTypeBlacklist = new ArrayMap<>();
+ /**
+ * Map of system pre-defined, uniquely named actors; keys are namespace,
+ * value maps actor name to package name.
+ */
+ private ArrayMap<String, ArrayMap<String, String>> mNamedActors = null;
+
public static SystemConfig getInstance() {
if (!isSystemProcess()) {
Slog.wtf(TAG, "SystemConfig is being accessed by a process other than "
@@ -398,12 +405,17 @@
return r;
}
+ @NonNull
+ public Map<String, ? extends Map<String, String>> getNamedActors() {
+ return mNamedActors != null ? mNamedActors : Collections.emptyMap();
+ }
+
/**
* Only use for testing. Do NOT use in production code.
* @param readPermissions false to create an empty SystemConfig; true to read the permissions.
*/
@VisibleForTesting
- protected SystemConfig(boolean readPermissions) {
+ public SystemConfig(boolean readPermissions) {
if (readPermissions) {
Slog.w(TAG, "Constructing a test SystemConfig");
readAllPermissions();
@@ -1028,6 +1040,44 @@
readInstallInUserType(parser,
mPackageToUserTypeWhitelist, mPackageToUserTypeBlacklist);
} break;
+ case "named-actor": {
+ String namespace = TextUtils.safeIntern(
+ parser.getAttributeValue(null, "namespace"));
+ String actorName = parser.getAttributeValue(null, "name");
+ String pkgName = TextUtils.safeIntern(
+ parser.getAttributeValue(null, "package"));
+ if (TextUtils.isEmpty(namespace)) {
+ Slog.wtf(TAG, "<" + name + "> without namespace in " + permFile
+ + " at " + parser.getPositionDescription());
+ } else if (TextUtils.isEmpty(actorName)) {
+ Slog.wtf(TAG, "<" + name + "> without actor name in " + permFile
+ + " at " + parser.getPositionDescription());
+ } else if (TextUtils.isEmpty(pkgName)) {
+ Slog.wtf(TAG, "<" + name + "> without package name in " + permFile
+ + " at " + parser.getPositionDescription());
+ } else if ("android".equalsIgnoreCase(namespace)) {
+ throw new IllegalStateException("Defining " + actorName + " as "
+ + pkgName + " for the android namespace is not allowed");
+ } else {
+ if (mNamedActors == null) {
+ mNamedActors = new ArrayMap<>();
+ }
+
+ ArrayMap<String, String> nameToPkgMap = mNamedActors.get(namespace);
+ if (nameToPkgMap == null) {
+ nameToPkgMap = new ArrayMap<>();
+ mNamedActors.put(namespace, nameToPkgMap);
+ } else if (nameToPkgMap.containsKey(actorName)) {
+ String existing = nameToPkgMap.get(actorName);
+ throw new IllegalStateException("Duplicate actor definition for "
+ + namespace + "/" + actorName
+ + "; defined as both " + existing + " and " + pkgName);
+ }
+
+ nameToPkgMap.put(actorName, pkgName);
+ }
+ XmlUtils.skipCurrentTag(parser);
+ } break;
default: {
Slog.w(TAG, "Tag " + name + " is unknown in "
+ permFile + " at " + parser.getPositionDescription());
diff --git a/core/jni/android_content_res_ApkAssets.cpp b/core/jni/android_content_res_ApkAssets.cpp
index 6370253..f3a626e 100644
--- a/core/jni/android_content_res_ApkAssets.cpp
+++ b/core/jni/android_content_res_ApkAssets.cpp
@@ -194,6 +194,59 @@
return reinterpret_cast<jlong>(xml_tree.release());
}
+static jobject NativeGetOverlayableInfo(JNIEnv* env, jclass /*clazz*/, jlong ptr,
+ jstring overlayable_name) {
+ const ApkAssets* apk_assets = reinterpret_cast<const ApkAssets*>(ptr);
+
+ const auto& packages = apk_assets->GetLoadedArsc()->GetPackages();
+ if (packages.empty()) {
+ jniThrowException(env, "java/io/IOException", "Error reading overlayable from APK");
+ return 0;
+ }
+
+ // TODO(b/119899133): Convert this to a search for the info rather than assuming it's at index 0
+ const auto& overlayable_map = packages[0]->GetOverlayableMap();
+ if (overlayable_map.empty()) {
+ return nullptr;
+ }
+
+ auto overlayable_name_native = std::string(env->GetStringUTFChars(overlayable_name, NULL));
+ auto actor = overlayable_map.find(overlayable_name_native);
+ if (actor == overlayable_map.end()) {
+ return nullptr;
+ }
+
+ jstring actor_string = env->NewStringUTF(actor->first.c_str());
+ if (env->ExceptionCheck() || actor_string == nullptr) {
+ jniThrowException(env, "java/io/IOException", "Error reading overlayable from APK");
+ return 0;
+ }
+
+ jclass overlayable_class = env->FindClass("android/content/om/OverlayableInfo");
+ jmethodID overlayable_constructor = env->GetMethodID(overlayable_class, "<init>",
+ "(Ljava/lang/String;Ljava/lang/String;I)V");
+ return env->NewObject(
+ overlayable_class,
+ overlayable_constructor,
+ overlayable_name,
+ actor_string
+ );
+}
+
+static jboolean NativeDefinesOverlayable(JNIEnv* env, jclass /*clazz*/, jlong ptr) {
+ const ApkAssets* apk_assets = reinterpret_cast<const ApkAssets*>(ptr);
+
+ const auto& packages = apk_assets->GetLoadedArsc()->GetPackages();
+ if (packages.empty()) {
+ // Must throw to prevent bypass by returning false
+ jniThrowException(env, "java/io/IOException", "Error reading overlayable from APK");
+ return 0;
+ }
+
+ const auto& overlayable_infos = packages[0]->GetOverlayableMap();
+ return overlayable_infos.empty() ? JNI_FALSE : JNI_TRUE;
+}
+
// JNI registration.
static const JNINativeMethod gApkAssetsMethods[] = {
{"nativeLoad", "(Ljava/lang/String;ZZZZ)J", (void*)NativeLoad},
@@ -208,6 +261,9 @@
{"nativeGetStringBlock", "(J)J", (void*)NativeGetStringBlock},
{"nativeIsUpToDate", "(J)Z", (void*)NativeIsUpToDate},
{"nativeOpenXml", "(JLjava/lang/String;)J", (void*)NativeOpenXml},
+ {"nativeGetOverlayableInfo", "(JLjava/lang/String;)Landroid/content/om/OverlayableInfo;",
+ (void*)NativeGetOverlayableInfo},
+ {"nativeDefinesOverlayable", "(J)Z", (void*)NativeDefinesOverlayable},
};
int register_android_content_res_ApkAssets(JNIEnv* env) {
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index f8a2744..9f20388 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -491,6 +491,7 @@
float* floatColors = env->GetFloatArrayElements(fColor, 0);
half3 color(floatColors[0], floatColors[1], floatColors[2]);
transaction->setColor(ctrl, color);
+ env->ReleaseFloatArrayElements(fColor, floatColors, 0);
}
static void nativeSetMatrix(JNIEnv* env, jclass clazz, jlong transactionObj,
@@ -508,8 +509,12 @@
SurfaceControl* const surfaceControl = reinterpret_cast<SurfaceControl*>(nativeObject);
float* floatMatrix = env->GetFloatArrayElements(fMatrix, 0);
mat3 matrix(static_cast<float const*>(floatMatrix));
+ env->ReleaseFloatArrayElements(fMatrix, floatMatrix, 0);
+
float* floatTranslation = env->GetFloatArrayElements(fTranslation, 0);
vec3 translation(floatTranslation[0], floatTranslation[1], floatTranslation[2]);
+ env->ReleaseFloatArrayElements(fTranslation, floatTranslation, 0);
+
transaction->setColorTransform(surfaceControl, matrix, translation);
}
@@ -1262,6 +1267,22 @@
return reinterpret_cast<jlong>(surface.get());
}
+static void nativeSetGlobalShadowSettings(JNIEnv* env, jclass clazz, jfloatArray jAmbientColor,
+ jfloatArray jSpotColor, jfloat lightPosY, jfloat lightPosZ, jfloat lightRadius) {
+ sp<SurfaceComposerClient> client = SurfaceComposerClient::getDefault();
+
+ float* floatAmbientColor = env->GetFloatArrayElements(jAmbientColor, 0);
+ half4 ambientColor = half4(floatAmbientColor[0], floatAmbientColor[1], floatAmbientColor[2],
+ floatAmbientColor[3]);
+ env->ReleaseFloatArrayElements(jAmbientColor, floatAmbientColor, 0);
+
+ float* floatSpotColor = env->GetFloatArrayElements(jSpotColor, 0);
+ half4 spotColor = half4(floatSpotColor[0], floatSpotColor[1], floatSpotColor[2],
+ floatSpotColor[3]);
+ env->ReleaseFloatArrayElements(jSpotColor, floatSpotColor, 0);
+
+ client->setGlobalShadowSettings(ambientColor, spotColor, lightPosY, lightPosZ, lightRadius);
+}
// ----------------------------------------------------------------------------
static const JNINativeMethod sSurfaceControlMethods[] = {
@@ -1416,6 +1437,8 @@
(void*)nativeWriteTransactionToParcel },
{"nativeMirrorSurface", "(J)J",
(void*)nativeMirrorSurface },
+ {"nativeSetGlobalShadowSettings", "([F[FFFF)V",
+ (void*)nativeSetGlobalShadowSettings },
};
int register_android_view_SurfaceControl(JNIEnv* env)
diff --git a/core/tests/coretests/src/android/os/WorkSourceTest.java b/core/tests/coretests/src/android/os/WorkSourceTest.java
index e94d60c..4206fd2 100644
--- a/core/tests/coretests/src/android/os/WorkSourceTest.java
+++ b/core/tests/coretests/src/android/os/WorkSourceTest.java
@@ -228,13 +228,13 @@
WorkSource ws = new WorkSource();
ws.set(10);
assertEquals(1, ws.size());
- assertEquals(10, ws.get(0));
+ assertEquals(10, ws.getUid(0));
WorkSource ws2 = new WorkSource();
ws2.set(20, "foo");
assertEquals(1, ws2.size());
- assertEquals(20, ws2.get(0));
- assertEquals("foo", ws2.getName(0));
+ assertEquals(20, ws2.getUid(0));
+ assertEquals("foo", ws2.getPackageName(0));
}
public void testDiffChains_noChanges() {
@@ -410,8 +410,8 @@
assertTrue(ws2.remove(ws1));
assertEquals(0, ws1.size());
- assertEquals(50, ws1.get(0));
- assertEquals("foo", ws1.getName(0));
+ assertEquals(50, ws1.getUid(0));
+ assertEquals("foo", ws1.getPackageName(0));
}
public void testTransferWorkChains() {
diff --git a/libs/androidfw/include/androidfw/LoadedArsc.h b/libs/androidfw/include/androidfw/LoadedArsc.h
index 6cbda07..b5d3a1f 100644
--- a/libs/androidfw/include/androidfw/LoadedArsc.h
+++ b/libs/androidfw/include/androidfw/LoadedArsc.h
@@ -273,6 +273,8 @@
ByteBucketArray<uint32_t> resource_ids_;
std::vector<DynamicPackageEntry> dynamic_package_map_;
std::vector<const std::pair<OverlayableInfo, std::unordered_set<uint32_t>>> overlayable_infos_;
+
+ // A map of overlayable name to actor
std::unordered_map<std::string, std::string> overlayable_map_;
};
diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java
index e1f6597..34c5842 100644
--- a/services/core/java/com/android/server/LocationManagerService.java
+++ b/services/core/java/com/android/server/LocationManagerService.java
@@ -1947,11 +1947,11 @@
if (workSource.size() > 0) {
// If the WorkSource has one or more non-chained UIDs, make sure they're accompanied
// by tags.
- return workSource.getName(0) != null;
+ return workSource.getPackageName(0) != null;
} else {
// For now, make sure callers have supplied an attribution tag for use with
// AppOpsManager. This might be relaxed in the future.
- final ArrayList<WorkChain> workChains = workSource.getWorkChains();
+ final List<WorkChain> workChains = workSource.getWorkChains();
return workChains != null && !workChains.isEmpty() &&
workChains.get(0).getAttributionTag() != null;
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 3dc745b..88d0e4b 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -8649,7 +8649,7 @@
mBatteryStatsService.noteWakupAlarm(sourcePkg, sourceUid, workSource, tag);
if (workSource != null) {
- String workSourcePackage = workSource.getName(0);
+ String workSourcePackage = workSource.getPackageName(0);
int workSourceUid = workSource.getAttributionUid();
if (workSourcePackage == null) {
workSourcePackage = sourcePkg;
diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java
index 637bcae..c84745e 100644
--- a/services/core/java/com/android/server/location/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/GnssLocationProvider.java
@@ -1169,14 +1169,15 @@
if (newWork != null) {
for (int i = 0; i < newWork.size(); i++) {
mAppOps.startOpNoThrow(AppOpsManager.OP_GPS,
- newWork.get(i), newWork.getName(i));
+ newWork.getUid(i), newWork.getPackageName(i));
}
}
// Update sources that are no longer tracked.
if (goneWork != null) {
for (int i = 0; i < goneWork.size(); i++) {
- mAppOps.finishOp(AppOpsManager.OP_GPS, goneWork.get(i), goneWork.getName(i));
+ mAppOps.finishOp(AppOpsManager.OP_GPS, goneWork.getUid(i),
+ goneWork.getPackageName(i));
}
}
}
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 0ae4a8f..b60306b 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -360,9 +360,11 @@
private static final String EXTRA_KEY = "key";
/**
- * Apps targeting R+ that post custom toasts in the background will have those blocked. Apps can
+ * Apps that post custom toasts in the background will have those blocked. Apps can
* still post toasts created with {@link Toast#makeText(Context, CharSequence, int)} and its
* variants while in the background.
+ *
+ * TODO(b/144152069): Add @EnabledAfter(Q) to target R+ after assessing impact on dogfood
*/
@ChangeId
private static final long CHANGE_BACKGROUND_CUSTOM_TOAST_BLOCK = 128611929L;
diff --git a/services/core/java/com/android/server/om/OverlayActorEnforcer.java b/services/core/java/com/android/server/om/OverlayActorEnforcer.java
new file mode 100644
index 0000000..e055116
--- /dev/null
+++ b/services/core/java/com/android/server/om/OverlayActorEnforcer.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 com.android.server.om;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.om.OverlayInfo;
+import android.content.om.OverlayableInfo;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+import android.net.Uri;
+import android.os.Process;
+import android.os.RemoteException;
+import android.text.TextUtils;
+
+import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.CollectionUtils;
+import com.android.server.SystemConfig;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Performs verification that a calling UID can act on a target package's overlayable.
+ *
+ * @hide
+ */
+public class OverlayActorEnforcer {
+
+ private final VerifyCallback mVerifyCallback;
+
+ public OverlayActorEnforcer(@NonNull VerifyCallback verifyCallback) {
+ mVerifyCallback = verifyCallback;
+ }
+
+ void enforceActor(@NonNull OverlayInfo overlayInfo, @NonNull String methodName,
+ int callingUid, int userId) throws SecurityException {
+ ActorState actorState = isAllowedActor(methodName, overlayInfo, callingUid, userId);
+ if (actorState == ActorState.ALLOWED) {
+ return;
+ }
+
+ String targetOverlayableName = overlayInfo.targetOverlayableName;
+ throw new SecurityException("UID" + callingUid + " is not allowed to call "
+ + methodName + " for "
+ + (TextUtils.isEmpty(targetOverlayableName) ? "" : (targetOverlayableName + " in "))
+ + overlayInfo.targetPackageName + " because " + actorState
+ );
+ }
+
+ /**
+ * An actor is valid if any of the following is true:
+ * - is {@link Process#ROOT_UID}, {@link Process#SYSTEM_UID}
+ * - is the target overlay package
+ * - has the CHANGE_OVERLAY_PACKAGES permission and an actor is not defined
+ * - is the same the as the package defined in {@link SystemConfig#getNamedActors()} for a given
+ * namespace and actor name
+ *
+ * @return true if the actor is allowed to act on the target overlayInfo
+ */
+ private ActorState isAllowedActor(String methodName, OverlayInfo overlayInfo,
+ int callingUid, int userId) {
+ switch (callingUid) {
+ case Process.ROOT_UID:
+ case Process.SYSTEM_UID:
+ return ActorState.ALLOWED;
+ }
+
+ String[] callingPackageNames = mVerifyCallback.getPackagesForUid(callingUid);
+ if (ArrayUtils.isEmpty(callingPackageNames)) {
+ return ActorState.NO_PACKAGES_FOR_UID;
+ }
+
+ // A target is always an allowed actor for itself
+ String targetPackageName = overlayInfo.targetPackageName;
+ if (ArrayUtils.contains(callingPackageNames, targetPackageName)) {
+ return ActorState.ALLOWED;
+ }
+
+ String targetOverlayableName = overlayInfo.targetOverlayableName;
+
+ if (TextUtils.isEmpty(targetOverlayableName)) {
+ try {
+ if (mVerifyCallback.doesTargetDefineOverlayable(targetPackageName, userId)) {
+ return ActorState.MISSING_TARGET_OVERLAYABLE_NAME;
+ } else {
+ // If there's no overlayable defined, fallback to the legacy permission check
+ try {
+ mVerifyCallback.enforcePermission(
+ android.Manifest.permission.CHANGE_OVERLAY_PACKAGES, methodName);
+
+ // If the previous method didn't throw, check passed
+ return ActorState.ALLOWED;
+ } catch (SecurityException e) {
+ return ActorState.MISSING_LEGACY_PERMISSION;
+ }
+ }
+ } catch (RemoteException | IOException e) {
+ return ActorState.ERROR_READING_OVERLAYABLE;
+ }
+ }
+
+ OverlayableInfo targetOverlayable;
+ try {
+ targetOverlayable = mVerifyCallback.getOverlayableForTarget(targetPackageName,
+ targetOverlayableName, userId);
+ } catch (IOException e) {
+ return ActorState.UNABLE_TO_GET_TARGET;
+ }
+
+ if (targetOverlayable == null) {
+ return ActorState.MISSING_OVERLAYABLE;
+ }
+
+ String actor = targetOverlayable.actor;
+ if (TextUtils.isEmpty(actor)) {
+ // If there's no actor defined, fallback to the legacy permission check
+ try {
+ mVerifyCallback.enforcePermission(
+ android.Manifest.permission.CHANGE_OVERLAY_PACKAGES, methodName);
+
+ // If the previous method didn't throw, check passed
+ return ActorState.ALLOWED;
+ } catch (SecurityException e) {
+ return ActorState.MISSING_LEGACY_PERMISSION;
+ }
+ }
+
+ Map<String, ? extends Map<String, String>> namedActors = mVerifyCallback.getNamedActors();
+ if (namedActors.isEmpty()) {
+ return ActorState.NO_NAMED_ACTORS;
+ }
+
+ Uri actorUri = Uri.parse(actor);
+
+ String actorScheme = actorUri.getScheme();
+ List<String> actorPathSegments = actorUri.getPathSegments();
+ if (!"overlay".equals(actorScheme) || CollectionUtils.size(actorPathSegments) != 1) {
+ return ActorState.INVALID_OVERLAYABLE_ACTOR_NAME;
+ }
+
+ String actorNamespace = actorUri.getAuthority();
+ Map<String, String> namespace = namedActors.get(actorNamespace);
+ if (namespace == null) {
+ return ActorState.MISSING_NAMESPACE;
+ }
+
+ String actorName = actorPathSegments.get(0);
+ String packageName = namespace.get(actorName);
+ if (TextUtils.isEmpty(packageName)) {
+ return ActorState.MISSING_ACTOR_NAME;
+ }
+
+ PackageInfo packageInfo = mVerifyCallback.getPackageInfo(packageName, userId);
+ if (packageInfo == null) {
+ return ActorState.MISSING_APP_INFO;
+ }
+
+ ApplicationInfo appInfo = packageInfo.applicationInfo;
+ if (appInfo == null) {
+ return ActorState.MISSING_APP_INFO;
+ }
+
+ // Currently only pre-installed apps can be actors
+ if (!appInfo.isSystemApp() && !appInfo.isUpdatedSystemApp()) {
+ return ActorState.ACTOR_NOT_PREINSTALLED;
+ }
+
+ if (ArrayUtils.contains(callingPackageNames, packageName)) {
+ return ActorState.ALLOWED;
+ }
+
+ return ActorState.INVALID_ACTOR;
+ }
+
+ /**
+ * For easier logging/debugging, a set of all possible failure/success states when running
+ * enforcement.
+ */
+ private enum ActorState {
+ ALLOWED,
+ INVALID_ACTOR,
+ MISSING_NAMESPACE,
+ MISSING_PACKAGE,
+ MISSING_APP_INFO,
+ ACTOR_NOT_PREINSTALLED,
+ NO_PACKAGES_FOR_UID,
+ MISSING_ACTOR_NAME,
+ ERROR_READING_OVERLAYABLE,
+ MISSING_TARGET_OVERLAYABLE_NAME,
+ MISSING_OVERLAYABLE,
+ INVALID_OVERLAYABLE_ACTOR_NAME,
+ NO_NAMED_ACTORS,
+ UNABLE_TO_GET_TARGET,
+ MISSING_LEGACY_PERMISSION
+ }
+
+ /**
+ * Delegate to the system for querying information about packages.
+ */
+ public interface VerifyCallback {
+
+ /**
+ * Read from the APK and AndroidManifest of a package to return the overlayable defined for
+ * a given name.
+ *
+ * @throws IOException if the target can't be read
+ */
+ @Nullable
+ OverlayableInfo getOverlayableForTarget(@NonNull String packageName,
+ @Nullable String targetOverlayableName, int userId)
+ throws IOException;
+
+ /**
+ * @see android.content.pm.PackageManager#getPackagesForUid(int)
+ */
+ @Nullable
+ String[] getPackagesForUid(int uid);
+
+ /**
+ * @param userId user to filter package visibility by
+ * @see android.content.pm.PackageManager#getPackageInfo(String, int)
+ */
+ @Nullable
+ PackageInfo getPackageInfo(@NonNull String packageName, int userId);
+
+ /**
+ * @return map of system pre-defined, uniquely named actors; keys are namespace,
+ * value maps actor name to package name
+ */
+ @NonNull
+ Map<String, ? extends Map<String, String>> getNamedActors();
+
+ /**
+ * @return true if the target package has declared an overlayable
+ */
+ boolean doesTargetDefineOverlayable(String targetPackageName, int userId)
+ throws RemoteException, IOException;
+
+ /**
+ * @throws SecurityException containing message if the caller doesn't have the given
+ * permission
+ */
+ void enforcePermission(String permission, String message) throws SecurityException;
+ }
+}
diff --git a/services/core/java/com/android/server/om/OverlayManagerService.java b/services/core/java/com/android/server/om/OverlayManagerService.java
index 5f3e503..63de61c 100644
--- a/services/core/java/com/android/server/om/OverlayManagerService.java
+++ b/services/core/java/com/android/server/om/OverlayManagerService.java
@@ -39,10 +39,12 @@
import android.content.IntentFilter;
import android.content.om.IOverlayManager;
import android.content.om.OverlayInfo;
+import android.content.om.OverlayableInfo;
import android.content.pm.IPackageManager;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManagerInternal;
import android.content.pm.UserInfo;
+import android.content.res.ApkAssets;
import android.net.Uri;
import android.os.Binder;
import android.os.Environment;
@@ -63,6 +65,7 @@
import com.android.server.FgThread;
import com.android.server.IoThread;
import com.android.server.LocalServices;
+import com.android.server.SystemConfig;
import com.android.server.SystemService;
import com.android.server.pm.UserManagerService;
@@ -229,6 +232,8 @@
private final OverlayManagerServiceImpl mImpl;
+ private final OverlayActorEnforcer mActorEnforcer;
+
private final AtomicBoolean mPersistSettingsScheduled = new AtomicBoolean(false);
public OverlayManagerService(@NonNull final Context context) {
@@ -237,12 +242,13 @@
traceBegin(TRACE_TAG_RRO, "OMS#OverlayManagerService");
mSettingsFile = new AtomicFile(
new File(Environment.getDataSystemDirectory(), "overlays.xml"), "overlays");
- mPackageManager = new PackageManagerHelper();
+ mPackageManager = new PackageManagerHelper(context);
mUserManager = UserManagerService.getInstance();
IdmapManager im = new IdmapManager(mPackageManager);
mSettings = new OverlayManagerSettings();
mImpl = new OverlayManagerServiceImpl(mPackageManager, im, mSettings,
getDefaultOverlayPackages(), new OverlayChangeListener());
+ mActorEnforcer = new OverlayActorEnforcer(mPackageManager);
final IntentFilter packageFilter = new IntentFilter();
packageFilter.addAction(ACTION_PACKAGE_ADDED);
@@ -581,7 +587,7 @@
int userId) throws RemoteException {
try {
traceBegin(TRACE_TAG_RRO, "OMS#setEnabled " + packageName + " " + enable);
- enforceChangeOverlayPackagesPermission("setEnabled");
+ enforceActor(packageName, "setEnabled", userId);
userId = handleIncomingUser(userId, "setEnabled");
if (packageName == null) {
return false;
@@ -605,7 +611,7 @@
int userId) throws RemoteException {
try {
traceBegin(TRACE_TAG_RRO, "OMS#setEnabledExclusive " + packageName + " " + enable);
- enforceChangeOverlayPackagesPermission("setEnabledExclusive");
+ enforceActor(packageName, "setEnabledExclusive", userId);
userId = handleIncomingUser(userId, "setEnabledExclusive");
if (packageName == null || !enable) {
return false;
@@ -630,7 +636,7 @@
throws RemoteException {
try {
traceBegin(TRACE_TAG_RRO, "OMS#setEnabledExclusiveInCategory " + packageName);
- enforceChangeOverlayPackagesPermission("setEnabledExclusiveInCategory");
+ enforceActor(packageName, "setEnabledExclusiveInCategory", userId);
userId = handleIncomingUser(userId, "setEnabledExclusiveInCategory");
if (packageName == null) {
return false;
@@ -656,7 +662,7 @@
try {
traceBegin(TRACE_TAG_RRO, "OMS#setPriority " + packageName + " "
+ parentPackageName);
- enforceChangeOverlayPackagesPermission("setPriority");
+ enforceActor(packageName, "setPriority", userId);
userId = handleIncomingUser(userId, "setPriority");
if (packageName == null || parentPackageName == null) {
return false;
@@ -680,7 +686,7 @@
throws RemoteException {
try {
traceBegin(TRACE_TAG_RRO, "OMS#setHighestPriority " + packageName);
- enforceChangeOverlayPackagesPermission("setHighestPriority");
+ enforceActor(packageName, "setHighestPriority", userId);
userId = handleIncomingUser(userId, "setHighestPriority");
if (packageName == null) {
return false;
@@ -704,7 +710,7 @@
throws RemoteException {
try {
traceBegin(TRACE_TAG_RRO, "OMS#setLowestPriority " + packageName);
- enforceChangeOverlayPackagesPermission("setLowestPriority");
+ enforceActor(packageName, "setLowestPriority", userId);
userId = handleIncomingUser(userId, "setLowestPriority");
if (packageName == null) {
return false;
@@ -750,7 +756,7 @@
return;
}
- enforceChangeOverlayPackagesPermission("invalidateCachesForOverlay");
+ enforceActor(packageName, "invalidateCachesForOverlay", userId);
userId = handleIncomingUser(userId, "invalidateCachesForOverlay");
final long ident = Binder.clearCallingIdentity();
try {
@@ -861,18 +867,6 @@
}
/**
- * Enforce that the caller holds the CHANGE_OVERLAY_PACKAGES permission (or is
- * system or root).
- *
- * @param message used as message if SecurityException is thrown
- * @throws SecurityException if the permission check fails
- */
- private void enforceChangeOverlayPackagesPermission(@NonNull final String message) {
- getContext().enforceCallingOrSelfPermission(
- android.Manifest.permission.CHANGE_OVERLAY_PACKAGES, message);
- }
-
- /**
* Enforce that the caller holds the DUMP permission (or is system or root).
*
* @param message used as message if SecurityException is thrown
@@ -881,6 +875,13 @@
private void enforceDumpPermission(@NonNull final String message) {
getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, message);
}
+
+ private void enforceActor(String packageName, String methodName, int userId)
+ throws SecurityException {
+ OverlayInfo overlayInfo = mImpl.getOverlayInfo(packageName, userId);
+ int callingUid = Binder.getCallingUid();
+ mActorEnforcer.enforceActor(overlayInfo, methodName, callingUid, userId);
+ }
};
private final class OverlayChangeListener
@@ -1035,9 +1036,16 @@
}
}
- private static final class PackageManagerHelper implements
- OverlayManagerServiceImpl.PackageManagerHelper {
+ /**
+ * Delegate for {@link android.content.pm.PackageManager} and {@link PackageManagerInternal}
+ * functionality, separated for easy testing.
+ *
+ * @hide
+ */
+ public static final class PackageManagerHelper implements
+ OverlayManagerServiceImpl.PackageManagerHelper, OverlayActorEnforcer.VerifyCallback {
+ private final Context mContext;
private final IPackageManager mPackageManager;
private final PackageManagerInternal mPackageManagerInternal;
@@ -1048,11 +1056,14 @@
// behind until all pending intents have been processed.
private final SparseArray<HashMap<String, PackageInfo>> mCache = new SparseArray<>();
- PackageManagerHelper() {
+ PackageManagerHelper(Context context) {
+ mContext = context;
mPackageManager = getPackageManager();
mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class);
}
+ // TODO(b/143096091): Remove PackageInfo cache so that PackageManager is always queried
+ // to enforce visibility/other permission checks
public PackageInfo getPackageInfo(@NonNull final String packageName, final int userId,
final boolean useCache) {
if (useCache) {
@@ -1075,7 +1086,19 @@
@Override
public PackageInfo getPackageInfo(@NonNull final String packageName, final int userId) {
- return getPackageInfo(packageName, userId, true);
+ // TODO(b/143096091): Remove clearing calling ID
+ long callingIdentity = Binder.clearCallingIdentity();
+ try {
+ return getPackageInfo(packageName, userId, true);
+ } finally {
+ Binder.restoreCallingIdentity(callingIdentity);
+ }
+ }
+
+ @NonNull
+ @Override
+ public Map<String, ? extends Map<String, String>> getNamedActors() {
+ return SystemConfig.getInstance().getNamedActors();
}
@Override
@@ -1097,6 +1120,70 @@
return mPackageManagerInternal.getOverlayPackages(userId);
}
+ @Nullable
+ @Override
+ public OverlayableInfo getOverlayableForTarget(@NonNull String packageName,
+ @Nullable String targetOverlayableName, int userId)
+ throws IOException {
+ // TODO(b/143096091): Remove clearing calling ID
+ long callingIdentity = Binder.clearCallingIdentity();
+ try {
+ PackageInfo packageInfo = getPackageInfo(packageName, userId);
+ if (packageInfo == null) {
+ throw new IOException("Unable to get target package");
+ }
+
+ String baseCodePath = packageInfo.applicationInfo.getBaseCodePath();
+
+ ApkAssets apkAssets = null;
+ try {
+ apkAssets = ApkAssets.loadFromPath(baseCodePath);
+ return apkAssets.getOverlayableInfo(targetOverlayableName);
+ } finally {
+ if (apkAssets != null) {
+ try {
+ apkAssets.close();
+ } catch (Throwable ignored) {
+ }
+ }
+ }
+ } finally {
+ Binder.restoreCallingIdentity(callingIdentity);
+ }
+ }
+
+ @Override
+ public boolean doesTargetDefineOverlayable(String targetPackageName, int userId)
+ throws RemoteException, IOException {
+ // TODO(b/143096091): Remove clearing calling ID
+ long callingIdentity = Binder.clearCallingIdentity();
+ try {
+ PackageInfo packageInfo = mPackageManager.getPackageInfo(targetPackageName, 0,
+ userId);
+ String baseCodePath = packageInfo.applicationInfo.getBaseCodePath();
+
+ ApkAssets apkAssets = null;
+ try {
+ apkAssets = ApkAssets.loadFromPath(baseCodePath);
+ return apkAssets.definesOverlayable();
+ } finally {
+ if (apkAssets != null) {
+ try {
+ apkAssets.close();
+ } catch (Throwable ignored) {
+ }
+ }
+ }
+ } finally {
+ Binder.restoreCallingIdentity(callingIdentity);
+ }
+ }
+
+ @Override
+ public void enforcePermission(String permission, String message) throws SecurityException {
+ mContext.enforceCallingOrSelfPermission(permission, message);
+ }
+
public PackageInfo getCachedPackageInfo(@NonNull final String packageName,
final int userId) {
final HashMap<String, PackageInfo> map = mCache.get(userId);
@@ -1128,6 +1215,22 @@
mCache.delete(userId);
}
+ @Nullable
+ @Override
+ public String[] getPackagesForUid(int uid) {
+ // TODO(b/143096091): Remove clearing calling ID
+ long callingIdentity = Binder.clearCallingIdentity();
+ try {
+ try {
+ return mPackageManager.getPackagesForUid(uid);
+ } catch (RemoteException ignored) {
+ return null;
+ }
+ } finally {
+ Binder.restoreCallingIdentity(callingIdentity);
+ }
+ }
+
private static final String TAB1 = " ";
private static final String TAB2 = TAB1 + TAB1;
diff --git a/services/core/java/com/android/server/pm/OWNERS b/services/core/java/com/android/server/pm/OWNERS
index 62ea95b..f8c173f 100644
--- a/services/core/java/com/android/server/pm/OWNERS
+++ b/services/core/java/com/android/server/pm/OWNERS
@@ -32,6 +32,9 @@
per-file CrossProfileIntentResolver.java = omakoto@google.com, yamasani@google.com
per-file UserManagerService.java = omakoto@google.com, yamasani@google.com
per-file UserRestrictionsUtils.java = omakoto@google.com, rubinxu@google.com, sandness@google.com, yamasani@google.com
+per-file UserSystemPackageInstaller.java = bookatz@google.com, omakoto@google.com, yamasani@google.com
+per-file UserTypeDetails.java = bookatz@google.com, omakoto@google.com, yamasani@google.com
+per-file UserTypeFactory.java = bookatz@google.com, omakoto@google.com, yamasani@google.com
# security
per-file KeySetHandle.java = cbrubaker@google.com, nnk@google.com
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index fce7f04..9cfd095 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -107,6 +107,7 @@
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.List;
import java.util.Objects;
/**
@@ -1174,9 +1175,9 @@
opPackageName = workChain.getAttributionTag();
opUid = workChain.getAttributionUid();
} else {
- opPackageName = workSource.getName(0) != null
- ? workSource.getName(0) : wakeLock.mPackageName;
- opUid = workSource.get(0);
+ opPackageName = workSource.getPackageName(0) != null
+ ? workSource.getPackageName(0) : wakeLock.mPackageName;
+ opUid = workSource.getUid(0);
}
} else {
opPackageName = wakeLock.mPackageName;
@@ -2004,13 +2005,13 @@
private boolean wakeLockAffectsUser(WakeLock wakeLock, @UserIdInt int userId) {
if (wakeLock.mWorkSource != null) {
for (int k = 0; k < wakeLock.mWorkSource.size(); k++) {
- final int uid = wakeLock.mWorkSource.get(k);
+ final int uid = wakeLock.mWorkSource.getUid(k);
if (userId == UserHandle.getUserId(uid)) {
return true;
}
}
- final ArrayList<WorkChain> workChains = wakeLock.mWorkSource.getWorkChains();
+ final List<WorkChain> workChains = wakeLock.mWorkSource.getWorkChains();
if (workChains != null) {
for (int k = 0; k < workChains.size(); k++) {
final int uid = workChains.get(k).getAttributionUid();
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/wm/ImeInsetsSourceProvider.java b/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java
index 11f09d0..a0b878c 100644
--- a/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java
+++ b/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java
@@ -92,12 +92,13 @@
// Refer to WindowManagerService#applyImeVisibility(token, false).
// If IMMS's imeTarget is child of DisplayContent's imeTarget and child window
// is above the parent, we will consider it as the same target for now.
+ // Also, if imeTarget is closing, it would be considered as outdated target.
// TODO(b/139861270): Remove the child & sublayer check once IMMS is aware of
// actual IME target.
- return mImeTargetFromIme == mDisplayContent.mInputMethodTarget
- || (mDisplayContent.mInputMethodTarget.getParentWindow() == mImeTargetFromIme
- && mDisplayContent.mInputMethodTarget.mSubLayer
- > mImeTargetFromIme.mSubLayer);
+ final WindowState dcTarget = mDisplayContent.mInputMethodTarget;
+ return (!dcTarget.isClosing() && mImeTargetFromIme == dcTarget)
+ || (dcTarget.getParentWindow() == mImeTargetFromIme
+ && dcTarget.mSubLayer > mImeTargetFromIme.mSubLayer);
}
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 2d6d5f4..a42f2e1 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -143,6 +143,7 @@
import android.content.pm.PackageManager;
import android.content.pm.PackageManagerInternal;
import android.content.res.Configuration;
+import android.content.res.TypedArray;
import android.database.ContentObserver;
import android.graphics.Bitmap;
import android.graphics.Insets;
@@ -1247,6 +1248,20 @@
LocalServices.addService(WindowManagerInternal.class, new LocalService());
mEmbeddedWindowController = new EmbeddedWindowController(mGlobalLock);
+ setGlobalShadowSettings();
+ }
+
+ private void setGlobalShadowSettings() {
+ final TypedArray a = mContext.obtainStyledAttributes(null, R.styleable.Lighting, 0, 0);
+ float lightY = a.getDimension(R.styleable.Lighting_lightY, 0);
+ float lightZ = a.getDimension(R.styleable.Lighting_lightZ, 0);
+ float lightRadius = a.getDimension(R.styleable.Lighting_lightRadius, 0);
+ float ambientShadowAlpha = a.getFloat(R.styleable.Lighting_ambientShadowAlpha, 0);
+ float spotShadowAlpha = a.getFloat(R.styleable.Lighting_spotShadowAlpha, 0);
+ float[] ambientColor = {0.f, 0.f, 0.f, ambientShadowAlpha};
+ float[] spotColor = {0.f, 0.f, 0.f, spotShadowAlpha};
+ SurfaceControl.setGlobalShadowSettings(ambientColor, spotColor, lightY, lightZ,
+ lightRadius);
}
/**
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/robotests/backup/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java b/services/robotests/backup/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java
index 6a90d0b..2510b60 100644
--- a/services/robotests/backup/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java
+++ b/services/robotests/backup/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java
@@ -713,7 +713,7 @@
// Verify has set work source and hasn't unset yet.
verify(mBackupManagerService)
.setWorkSource(
- argThat(workSource -> workSource.get(0) == PACKAGE_1.uid));
+ argThat(workSource -> workSource.getUid(0) == PACKAGE_1.uid));
verify(mBackupManagerService, never()).setWorkSource(null);
});
KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1);
diff --git a/services/tests/servicestests/Android.bp b/services/tests/servicestests/Android.bp
index 30ccb71..52fb69e 100644
--- a/services/tests/servicestests/Android.bp
+++ b/services/tests/servicestests/Android.bp
@@ -8,6 +8,7 @@
// Include all test java files.
srcs: [
"src/**/*.java",
+ "src/**/*.kt",
"aidl/com/android/servicestests/aidl/INetworkStateObserver.aidl",
"aidl/com/android/servicestests/aidl/ICmdReceiverService.aidl",
diff --git a/services/tests/servicestests/src/com/android/server/om/OverlayActorEnforcerTests.kt b/services/tests/servicestests/src/com/android/server/om/OverlayActorEnforcerTests.kt
new file mode 100644
index 0000000..233e16c
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/om/OverlayActorEnforcerTests.kt
@@ -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.om
+
+import android.content.om.OverlayInfo
+import android.content.om.OverlayableInfo
+import android.content.pm.ApplicationInfo
+import android.content.pm.PackageInfo
+import android.os.Process
+import org.junit.Rule
+import org.junit.Test
+import org.junit.rules.ExpectedException
+
+class OverlayActorEnforcerTests {
+ companion object {
+ private const val NAMESPACE = "testnamespace"
+ private const val ACTOR_NAME = "testactor"
+ private const val ACTOR_PKG_NAME = "com.test.actor.one"
+ private const val OVERLAYABLE_NAME = "TestOverlayable"
+ private const val UID = 3536
+ private const val USER_ID = 55
+ }
+
+ @get:Rule
+ val expectedException = ExpectedException.none()!!
+
+ @Test
+ fun isRoot() {
+ verify(callingUid = Process.ROOT_UID)
+ }
+
+ @Test(expected = SecurityException::class)
+ fun isShell() {
+ verify(callingUid = Process.SHELL_UID)
+ }
+
+ @Test
+ fun isSystem() {
+ verify(callingUid = Process.SYSTEM_UID)
+ }
+
+ @Test(expected = SecurityException::class)
+ fun noOverlayable_noTarget() {
+ verify(targetOverlayableName = null)
+ }
+
+ @Test
+ fun noOverlayable_noTarget_withPermission() {
+ verify(targetOverlayableName = null, hasPermission = true)
+ }
+
+ @Test(expected = SecurityException::class)
+ fun noOverlayable_withTarget() {
+ verify(targetOverlayableName = OVERLAYABLE_NAME)
+ }
+
+ @Test(expected = SecurityException::class)
+ fun withOverlayable_noTarget() {
+ verify(
+ targetOverlayableName = null,
+ overlayableInfo = OverlayableInfo(OVERLAYABLE_NAME, null)
+ )
+ }
+
+ @Test(expected = SecurityException::class)
+ fun withOverlayable_noActor() {
+ verify(
+ overlayableInfo = OverlayableInfo(OVERLAYABLE_NAME, null)
+ )
+ }
+
+ @Test
+ fun withOverlayable_noActor_withPermission() {
+ verify(
+ hasPermission = true,
+ overlayableInfo = OverlayableInfo(OVERLAYABLE_NAME, null)
+ )
+ }
+
+ @Test(expected = SecurityException::class)
+ fun withOverlayable_withActor_notActor() {
+ verify(
+ isActor = false,
+ overlayableInfo = OverlayableInfo(OVERLAYABLE_NAME,
+ "overlay://$NAMESPACE/$ACTOR_NAME")
+ )
+ }
+
+ @Test(expected = SecurityException::class)
+ fun withOverlayable_withActor_isActor_notPreInstalled() {
+ verify(
+ isActor = true,
+ isPreInstalled = false,
+ overlayableInfo = OverlayableInfo(OVERLAYABLE_NAME,
+ "overlay://$NAMESPACE/$ACTOR_NAME")
+ )
+ }
+
+ @Test
+ fun withOverlayable_withActor_isActor_isPreInstalled() {
+ verify(
+ isActor = true,
+ isPreInstalled = true,
+ overlayableInfo = OverlayableInfo(OVERLAYABLE_NAME,
+ "overlay://$NAMESPACE/$ACTOR_NAME")
+ )
+ }
+
+ @Test(expected = SecurityException::class)
+ fun withOverlayable_invalidActor() {
+ verify(
+ isActor = true,
+ isPreInstalled = true,
+ overlayableInfo = OverlayableInfo(OVERLAYABLE_NAME, "notValidActor")
+ )
+ }
+
+ private fun verify(
+ isActor: Boolean = false,
+ isPreInstalled: Boolean = false,
+ hasPermission: Boolean = false,
+ overlayableInfo: OverlayableInfo? = null,
+ callingUid: Int = UID,
+ targetOverlayableName: String? = OVERLAYABLE_NAME
+ ) {
+ val callback = MockCallback(
+ isActor = isActor,
+ isPreInstalled = isPreInstalled,
+ hasPermission = hasPermission,
+ overlayableInfo = overlayableInfo
+ )
+
+ val overlayInfo = overlayInfo(targetOverlayableName)
+ OverlayActorEnforcer(callback)
+ .enforceActor(overlayInfo, "test", callingUid, USER_ID)
+ }
+
+ private fun overlayInfo(targetOverlayableName: String?) = OverlayInfo("com.test.overlay",
+ "com.test.target", targetOverlayableName, null, "/path", OverlayInfo.STATE_UNKNOWN, 0,
+ 0, false)
+
+ private class MockCallback(
+ private val isActor: Boolean = false,
+ private val isPreInstalled: Boolean = false,
+ private val hasPermission: Boolean = false,
+ private val overlayableInfo: OverlayableInfo? = null,
+ private vararg val packageNames: String = arrayOf("com.test.actor.one")
+ ) : OverlayActorEnforcer.VerifyCallback {
+
+ override fun getNamedActors() = if (isActor) {
+ mapOf(NAMESPACE to mapOf(ACTOR_NAME to ACTOR_PKG_NAME))
+ } else {
+ emptyMap()
+ }
+
+ override fun getOverlayableForTarget(
+ packageName: String,
+ targetOverlayableName: String?,
+ userId: Int
+ ) = overlayableInfo
+
+ override fun getPackagesForUid(uid: Int) = when (uid) {
+ UID -> packageNames
+ else -> null
+ }
+
+ override fun getPackageInfo(packageName: String, userId: Int) = PackageInfo().apply {
+ applicationInfo = ApplicationInfo().apply {
+ flags = if (isPreInstalled) ApplicationInfo.FLAG_SYSTEM else 0
+ }
+ }
+
+ override fun doesTargetDefineOverlayable(targetPackageName: String?, userId: Int): Boolean {
+ return overlayableInfo != null
+ }
+
+ override fun enforcePermission(permission: String?, message: String?) {
+ if (!hasPermission) {
+ throw SecurityException()
+ }
+ }
+ }
+}
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/servicestests/src/com/android/server/systemconfig/SystemConfigNamedActorTest.kt b/services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigNamedActorTest.kt
new file mode 100644
index 0000000..b7199d4
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigNamedActorTest.kt
@@ -0,0 +1,232 @@
+/*
+ * 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.systemconfig
+
+import android.content.Context
+import androidx.test.InstrumentationRegistry
+import com.android.server.SystemConfig
+import com.google.common.truth.Truth.assertThat
+import org.junit.Rule
+import org.junit.Test
+import org.junit.rules.ExpectedException
+import org.junit.rules.TemporaryFolder
+
+class SystemConfigNamedActorTest {
+
+ companion object {
+ private const val NAMESPACE_TEST = "someTestNamespace"
+ private const val NAMESPACE_ANDROID = "android"
+ private const val ACTOR_ONE = "iconShaper"
+ private const val ACTOR_TWO = "colorChanger"
+ private const val PACKAGE_ONE = "com.test.actor.one"
+ private const val PACKAGE_TWO = "com.test.actor.two"
+ }
+
+ private val context: Context = InstrumentationRegistry.getContext()
+
+ @get:Rule
+ val tempFolder = TemporaryFolder(context.filesDir)
+
+ @get:Rule
+ val expected = ExpectedException.none()
+
+ private var uniqueCounter = 0
+
+ @Test
+ fun twoUnique() {
+ """
+ <config>
+ <named-actor
+ namespace="$NAMESPACE_TEST"
+ name="$ACTOR_ONE"
+ package="$PACKAGE_ONE"
+ />
+ <named-actor
+ namespace="$NAMESPACE_TEST"
+ name="$ACTOR_TWO"
+ package="$PACKAGE_TWO"
+ />
+ </config>
+ """.write()
+
+ assertPermissions().containsExactlyEntriesIn(
+ mapOf(
+ NAMESPACE_TEST to mapOf(
+ ACTOR_ONE to PACKAGE_ONE,
+ ACTOR_TWO to PACKAGE_TWO
+ )
+ )
+ )
+ }
+
+ @Test
+ fun twoSamePackage() {
+ """
+ <config>
+ <named-actor
+ namespace="$NAMESPACE_TEST"
+ name="$ACTOR_ONE"
+ package="$PACKAGE_ONE"
+ />
+ <named-actor
+ namespace="$NAMESPACE_TEST"
+ name="$ACTOR_TWO"
+ package="$PACKAGE_ONE"
+ />
+ </config>
+ """.write()
+
+ assertPermissions().containsExactlyEntriesIn(
+ mapOf(
+ NAMESPACE_TEST to mapOf(
+ ACTOR_ONE to PACKAGE_ONE,
+ ACTOR_TWO to PACKAGE_ONE
+ )
+ )
+ )
+ }
+
+ @Test
+ fun missingNamespace() {
+ """
+ <config>
+ <named-actor
+ name="$ACTOR_ONE"
+ package="$PACKAGE_ONE"
+ />
+ <named-actor
+ namespace="$NAMESPACE_TEST"
+ name="$ACTOR_TWO"
+ package="$PACKAGE_TWO"
+ />
+ </config>
+ """.write()
+
+ assertPermissions().containsExactlyEntriesIn(
+ mapOf(
+ NAMESPACE_TEST to mapOf(
+ ACTOR_TWO to PACKAGE_TWO
+ )
+ )
+ )
+ }
+
+ @Test
+ fun missingName() {
+ """
+ <config>
+ <named-actor
+ namespace="$NAMESPACE_TEST"
+ package="$PACKAGE_ONE"
+ />
+ <named-actor
+ namespace="$NAMESPACE_TEST"
+ name="$ACTOR_TWO"
+ package="$PACKAGE_TWO"
+ />
+ </config>
+ """.write()
+
+ assertPermissions().containsExactlyEntriesIn(
+ mapOf(
+ NAMESPACE_TEST to mapOf(
+ ACTOR_TWO to PACKAGE_TWO
+ )
+ )
+ )
+ }
+
+ @Test
+ fun missingPackage() {
+ """
+ <config>
+ <named-actor
+ namespace="$NAMESPACE_TEST"
+ name="$ACTOR_ONE"
+ />
+ <named-actor
+ namespace="$NAMESPACE_TEST"
+ name="$ACTOR_TWO"
+ package="$PACKAGE_TWO"
+ />
+ </config>
+ """.write()
+
+ assertPermissions().containsExactlyEntriesIn(
+ mapOf(
+ NAMESPACE_TEST to mapOf(
+ ACTOR_TWO to PACKAGE_TWO
+ )
+ )
+ )
+ }
+
+ @Test
+ fun androidNamespaceThrows() {
+ """
+ <config>
+ <named-actor
+ namespace="$NAMESPACE_TEST"
+ name="$ACTOR_ONE"
+ package="$PACKAGE_ONE"
+ />
+ <named-actor
+ namespace="$NAMESPACE_ANDROID"
+ name="$ACTOR_ONE"
+ package="$PACKAGE_ONE"
+ />
+ </config>
+ """.write()
+
+ expected.expect(IllegalStateException::class.java)
+ expected.expectMessage("Defining $ACTOR_ONE as $PACKAGE_ONE " +
+ "for the android namespace is not allowed")
+
+ assertPermissions()
+ }
+
+ @Test
+ fun duplicateActorNameThrows() {
+ """
+ <config>
+ <named-actor
+ namespace="$NAMESPACE_TEST"
+ name="$ACTOR_ONE"
+ package="$PACKAGE_ONE"
+ />
+ <named-actor
+ namespace="$NAMESPACE_TEST"
+ name="$ACTOR_ONE"
+ package="$PACKAGE_TWO"
+ />
+ </config>
+ """.write()
+
+ expected.expect(IllegalStateException::class.java)
+ expected.expectMessage("Duplicate actor definition for $NAMESPACE_TEST/$ACTOR_ONE;" +
+ " defined as both $PACKAGE_ONE and $PACKAGE_TWO")
+
+ assertPermissions()
+ }
+
+ private fun String.write() = tempFolder.root.resolve("${uniqueCounter++}.xml")
+ .writeText(this.trimIndent())
+
+ private fun assertPermissions() = SystemConfig(false).apply {
+ readPermissions(tempFolder.root, 0)
+ }. let { assertThat(it.namedActors) }
+}
diff --git a/services/tests/servicestests/src/com/android/server/SystemConfigTest.java b/services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigTest.java
similarity index 98%
rename from services/tests/servicestests/src/com/android/server/SystemConfigTest.java
rename to services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigTest.java
index ff03391..fde0ddf 100644
--- a/services/tests/servicestests/src/com/android/server/SystemConfigTest.java
+++ b/services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.server;
+package com.android.server.systemconfig;
import static org.junit.Assert.assertEquals;
@@ -25,6 +25,8 @@
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
+import com.android.server.SystemConfig;
+
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
diff --git a/telephony/java/android/telephony/TelephonyFrameworkInitializer.java b/telephony/java/android/telephony/TelephonyFrameworkInitializer.java
new file mode 100644
index 0000000..b75d533
--- /dev/null
+++ b/telephony/java/android/telephony/TelephonyFrameworkInitializer.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.telephony;
+
+import android.annotation.SystemApi;
+import android.app.SystemServiceRegistry;
+import android.content.Context;
+import android.telephony.euicc.EuiccCardManager;
+import android.telephony.euicc.EuiccManager;
+
+
+/**
+ * Class for performing registration for all telephony services.
+ *
+ * @hide
+ */
+@SystemApi
+public class TelephonyFrameworkInitializer {
+
+ private TelephonyFrameworkInitializer() {
+ }
+
+ /**
+ * Called by {@link SystemServiceRegistry}'s static initializer and registers all telephony
+ * 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.TELEPHONY_SERVICE,
+ TelephonyManager.class,
+ context -> new TelephonyManager(context)
+ );
+ SystemServiceRegistry.registerContextAwareService(
+ Context.TELEPHONY_SUBSCRIPTION_SERVICE,
+ SubscriptionManager.class,
+ context -> new SubscriptionManager(context)
+ );
+ SystemServiceRegistry.registerContextAwareService(
+ Context.CARRIER_CONFIG_SERVICE,
+ CarrierConfigManager.class,
+ context -> new CarrierConfigManager(context)
+ );
+ SystemServiceRegistry.registerContextAwareService(
+ Context.EUICC_SERVICE,
+ EuiccManager.class,
+ context -> new EuiccManager(context)
+ );
+ SystemServiceRegistry.registerContextAwareService(
+ Context.EUICC_CARD_SERVICE,
+ EuiccCardManager.class,
+ context -> new EuiccCardManager(context)
+ );
+ }
+}
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 60a2cd0..1357e9c 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -11298,7 +11298,9 @@
@IntDef(prefix = {"SET_OPPORTUNISTIC_SUB"}, value = {
SET_OPPORTUNISTIC_SUB_SUCCESS,
SET_OPPORTUNISTIC_SUB_VALIDATION_FAILED,
- SET_OPPORTUNISTIC_SUB_INACTIVE_SUBSCRIPTION})
+ SET_OPPORTUNISTIC_SUB_INACTIVE_SUBSCRIPTION,
+ SET_OPPORTUNISTIC_SUB_NO_OPPORTUNISTIC_SUB_AVAILABLE,
+ SET_OPPORTUNISTIC_SUB_REMOTE_SERVICE_EXCEPTION})
public @interface SetOpportunisticSubscriptionResult {}
/**
@@ -11316,6 +11318,17 @@
*/
public static final int SET_OPPORTUNISTIC_SUB_INACTIVE_SUBSCRIPTION = 2;
+ /**
+ * The subscription is not valid. It must be an opportunistic subscription.
+ */
+ public static final int SET_OPPORTUNISTIC_SUB_NO_OPPORTUNISTIC_SUB_AVAILABLE = 3;
+
+ /**
+ * Subscription service happened remote exception.
+ */
+ public static final int SET_OPPORTUNISTIC_SUB_REMOTE_SERVICE_EXCEPTION = 4;
+
+
/** @hide */
@Retention(RetentionPolicy.SOURCE)
@IntDef(prefix = {"UPDATE_AVAILABLE_NETWORKS"}, value = {
@@ -11323,7 +11336,13 @@
UPDATE_AVAILABLE_NETWORKS_UNKNOWN_FAILURE,
UPDATE_AVAILABLE_NETWORKS_ABORTED,
UPDATE_AVAILABLE_NETWORKS_INVALID_ARGUMENTS,
- UPDATE_AVAILABLE_NETWORKS_NO_CARRIER_PRIVILEGE})
+ UPDATE_AVAILABLE_NETWORKS_NO_CARRIER_PRIVILEGE,
+ UPDATE_AVAILABLE_NETWORKS_DISABLE_MODEM_FAIL,
+ UPDATE_AVAILABLE_NETWORKS_ENABLE_MODEM_FAIL,
+ UPDATE_AVAILABLE_NETWORKS_MULTIPLE_NETWORKS_NOT_SUPPORTED,
+ UPDATE_AVAILABLE_NETWORKS_NO_OPPORTUNISTIC_SUB_AVAILABLE,
+ UPDATE_AVAILABLE_NETWORKS_REMOTE_SERVICE_EXCEPTION,
+ UPDATE_AVAILABLE_NETWORKS_SERVICE_IS_DISABLED})
public @interface UpdateAvailableNetworksResult {}
/**
@@ -11352,6 +11371,36 @@
public static final int UPDATE_AVAILABLE_NETWORKS_NO_CARRIER_PRIVILEGE = 4;
/**
+ * Disable modem fail.
+ */
+ public static final int UPDATE_AVAILABLE_NETWORKS_DISABLE_MODEM_FAIL = 5;
+
+ /**
+ * Enable modem fail.
+ */
+ public static final int UPDATE_AVAILABLE_NETWORKS_ENABLE_MODEM_FAIL = 6;
+
+ /**
+ * Carrier app does not support multiple available networks.
+ */
+ public static final int UPDATE_AVAILABLE_NETWORKS_MULTIPLE_NETWORKS_NOT_SUPPORTED = 7;
+
+ /**
+ * The subscription is not valid. It must be an opportunistic subscription.
+ */
+ public static final int UPDATE_AVAILABLE_NETWORKS_NO_OPPORTUNISTIC_SUB_AVAILABLE = 8;
+
+ /**
+ * There is no OpportunisticNetworkService.
+ */
+ public static final int UPDATE_AVAILABLE_NETWORKS_REMOTE_SERVICE_EXCEPTION = 9;
+
+ /**
+ * OpportunisticNetworkService is disabled.
+ */
+ public static final int UPDATE_AVAILABLE_NETWORKS_SERVICE_IS_DISABLED = 10;
+
+ /**
* Set preferred opportunistic data subscription id.
*
* Switch internet data to preferred opportunistic data subscription id. This api
@@ -11381,7 +11430,7 @@
return;
}
Binder.withCleanCallingIdentity(() -> executor.execute(() -> {
- callback.accept(SET_OPPORTUNISTIC_SUB_INACTIVE_SUBSCRIPTION);
+ callback.accept(SET_OPPORTUNISTIC_SUB_REMOTE_SERVICE_EXCEPTION);
}));
return;
}
@@ -11467,9 +11516,8 @@
return;
}
if (iOpportunisticNetworkService == null) {
- /* Todo<b/130595455> passing unknown due to lack of good error codes */
Binder.withCleanCallingIdentity(() -> executor.execute(() -> {
- callback.accept(UPDATE_AVAILABLE_NETWORKS_UNKNOWN_FAILURE);
+ callback.accept(UPDATE_AVAILABLE_NETWORKS_REMOTE_SERVICE_EXCEPTION);
}));
} else {
Binder.withCleanCallingIdentity(() -> executor.execute(() -> {
diff --git a/telephony/java/com/android/internal/telephony/CarrierAppUtils.java b/telephony/java/com/android/internal/telephony/CarrierAppUtils.java
index 0d4fd0f..e6bebbb 100644
--- a/telephony/java/com/android/internal/telephony/CarrierAppUtils.java
+++ b/telephony/java/com/android/internal/telephony/CarrierAppUtils.java
@@ -25,10 +25,10 @@
import android.os.RemoteException;
import android.permission.IPermissionManager;
import android.provider.Settings;
+import android.telephony.Rlog;
import android.telephony.TelephonyManager;
import android.util.ArrayMap;
import android.util.ArraySet;
-import android.util.Slog;
import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
@@ -78,7 +78,7 @@
IPackageManager packageManager, IPermissionManager permissionManager,
TelephonyManager telephonyManager, ContentResolver contentResolver, int userId) {
if (DEBUG) {
- Slog.d(TAG, "disableCarrierAppsUntilPrivileged");
+ Rlog.d(TAG, "disableCarrierAppsUntilPrivileged");
}
SystemConfig config = SystemConfig.getInstance();
ArraySet<String> systemCarrierAppsDisabledUntilUsed =
@@ -105,7 +105,7 @@
IPackageManager packageManager, IPermissionManager permissionManager,
ContentResolver contentResolver, int userId) {
if (DEBUG) {
- Slog.d(TAG, "disableCarrierAppsUntilPrivileged");
+ Rlog.d(TAG, "disableCarrierAppsUntilPrivileged");
}
SystemConfig config = SystemConfig.getInstance();
ArraySet<String> systemCarrierAppsDisabledUntilUsed =
@@ -174,7 +174,7 @@
|| ai.enabledSetting ==
PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED
|| (ai.flags & ApplicationInfo.FLAG_INSTALLED) == 0)) {
- Slog.i(TAG, "Update state(" + packageName + "): ENABLED for user "
+ Rlog.i(TAG, "Update state(" + packageName + "): ENABLED for user "
+ userId);
packageManager.setSystemAppInstallState(
packageName,
@@ -197,7 +197,7 @@
PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED
|| (associatedApp.flags
& ApplicationInfo.FLAG_INSTALLED) == 0) {
- Slog.i(TAG, "Update associated state(" + associatedApp.packageName
+ Rlog.i(TAG, "Update associated state(" + associatedApp.packageName
+ "): ENABLED for user " + userId);
packageManager.setSystemAppInstallState(
associatedApp.packageName,
@@ -222,7 +222,7 @@
&& ai.enabledSetting ==
PackageManager.COMPONENT_ENABLED_STATE_DEFAULT
&& (ai.flags & ApplicationInfo.FLAG_INSTALLED) != 0) {
- Slog.i(TAG, "Update state(" + packageName
+ Rlog.i(TAG, "Update state(" + packageName
+ "): DISABLED_UNTIL_USED for user " + userId);
packageManager.setSystemAppInstallState(
packageName,
@@ -240,7 +240,7 @@
== PackageManager.COMPONENT_ENABLED_STATE_DEFAULT
&& (associatedApp.flags
& ApplicationInfo.FLAG_INSTALLED) != 0) {
- Slog.i(TAG,
+ Rlog.i(TAG,
"Update associated state(" + associatedApp.packageName
+ "): DISABLED_UNTIL_USED for user " + userId);
packageManager.setSystemAppInstallState(
@@ -268,7 +268,7 @@
permissionManager.grantDefaultPermissionsToEnabledCarrierApps(packageNames, userId);
}
} catch (RemoteException e) {
- Slog.w(TAG, "Could not reach PackageManager", e);
+ Rlog.w(TAG, "Could not reach PackageManager", e);
}
}
@@ -390,7 +390,7 @@
return ai;
}
} catch (RemoteException e) {
- Slog.w(TAG, "Could not reach PackageManager", e);
+ Rlog.w(TAG, "Could not reach PackageManager", e);
}
return null;
}
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmSmsCbMessage.java b/telephony/java/com/android/internal/telephony/gsm/GsmSmsCbMessage.java
index 5ce42fd..d03419d 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmSmsCbMessage.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmSmsCbMessage.java
@@ -30,10 +30,10 @@
import android.telephony.CbGeoUtils.Geometry;
import android.telephony.CbGeoUtils.LatLng;
import android.telephony.CbGeoUtils.Polygon;
+import android.telephony.Rlog;
import android.telephony.SmsCbLocation;
import android.telephony.SmsCbMessage;
import android.util.Pair;
-import android.util.Slog;
import com.android.internal.R;
import com.android.internal.telephony.GsmAlphabet;
@@ -131,7 +131,7 @@
} catch (Exception ex) {
// Catch the exception here, the message will be considered as having no WAC
// information which means the message will be broadcasted directly.
- Slog.e(TAG, "Can't parse warning area coordinates, ex = " + ex.toString());
+ Rlog.e(TAG, "Can't parse warning area coordinates, ex = " + ex.toString());
}
}
@@ -198,7 +198,7 @@
}
return new GeoFencingTriggerMessage(type, cbIdentifiers);
} catch (Exception ex) {
- Slog.e(TAG, "create geo-fencing trigger failed, ex = " + ex.toString());
+ Rlog.e(TAG, "create geo-fencing trigger failed, ex = " + ex.toString());
return null;
}
}
diff --git a/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassBase.java b/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassBase.java
index 176c7a0..339df93 100644
--- a/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassBase.java
+++ b/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassBase.java
@@ -32,7 +32,7 @@
- // Code below generated by codegen v1.0.13.
+ // Code below generated by codegen v1.0.14.
//
// DO NOT MODIFY!
// CHECKSTYLE:OFF Generated code
@@ -98,8 +98,8 @@
};
@DataClass.Generated(
- time = 1573006405823L,
- codegenVersion = "1.0.13",
+ time = 1574122837821L,
+ codegenVersion = "1.0.14",
sourceFile = "frameworks/base/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassBase.java",
inputSignatures = "private int mBaseData\nclass HierrarchicalDataClassBase extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genConstructor=false, genSetters=true)")
@Deprecated
diff --git a/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassChild.java b/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassChild.java
index e348c77..69e06b2 100644
--- a/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassChild.java
+++ b/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassChild.java
@@ -46,7 +46,7 @@
- // Code below generated by codegen v1.0.13.
+ // Code below generated by codegen v1.0.14.
//
// DO NOT MODIFY!
// CHECKSTYLE:OFF Generated code
@@ -120,8 +120,8 @@
};
@DataClass.Generated(
- time = 1573006406833L,
- codegenVersion = "1.0.13",
+ time = 1574122838768L,
+ codegenVersion = "1.0.14",
sourceFile = "frameworks/base/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassChild.java",
inputSignatures = "private @android.annotation.NonNull java.lang.String mChildData\nclass HierrarchicalDataClassChild extends com.android.codegentest.HierrarchicalDataClassBase implements []\n@com.android.internal.util.DataClass(genParcelable=true, genConstructor=false, genSetters=true)")
@Deprecated
diff --git a/tests/Codegen/src/com/android/codegentest/ParcelAllTheThingsDataClass.java b/tests/Codegen/src/com/android/codegentest/ParcelAllTheThingsDataClass.java
index 112d3df..ca128be 100644
--- a/tests/Codegen/src/com/android/codegentest/ParcelAllTheThingsDataClass.java
+++ b/tests/Codegen/src/com/android/codegentest/ParcelAllTheThingsDataClass.java
@@ -54,7 +54,7 @@
- // Code below generated by codegen v1.0.13.
+ // Code below generated by codegen v1.0.14.
//
// DO NOT MODIFY!
// CHECKSTYLE:OFF Generated code
@@ -291,7 +291,7 @@
/** @see #setStringList */
@DataClass.Generated.Member
- public @NonNull Builder addStringList(String value) {
+ public @NonNull Builder addStringList(@NonNull String value) {
// You can refine this method's name by providing item's singular name, e.g.:
// @DataClass.PluralOf("item")) mItems = ...
@@ -310,7 +310,7 @@
/** @see #setMap */
@DataClass.Generated.Member
- public @NonNull Builder addMap(String key, SampleWithCustomBuilder value) {
+ public @NonNull Builder addMap(@NonNull String key, @NonNull SampleWithCustomBuilder value) {
// You can refine this method's name by providing item's singular name, e.g.:
// @DataClass.PluralOf("item")) mItems = ...
@@ -329,7 +329,7 @@
/** @see #setStringMap */
@DataClass.Generated.Member
- public @NonNull Builder addStringMap(String key, String value) {
+ public @NonNull Builder addStringMap(@NonNull String key, @NonNull String value) {
// You can refine this method's name by providing item's singular name, e.g.:
// @DataClass.PluralOf("item")) mItems = ...
@@ -412,8 +412,8 @@
}
@DataClass.Generated(
- time = 1573006404728L,
- codegenVersion = "1.0.13",
+ time = 1574122836960L,
+ codegenVersion = "1.0.14",
sourceFile = "frameworks/base/tests/Codegen/src/com/android/codegentest/ParcelAllTheThingsDataClass.java",
inputSignatures = " @android.annotation.NonNull java.lang.String[] mStringArray\n @android.annotation.NonNull int[] mIntArray\n @android.annotation.NonNull java.util.List<java.lang.String> mStringList\n @android.annotation.NonNull java.util.Map<java.lang.String,com.android.codegentest.SampleWithCustomBuilder> mMap\n @android.annotation.NonNull java.util.Map<java.lang.String,java.lang.String> mStringMap\n @android.annotation.NonNull android.util.SparseArray<com.android.codegentest.SampleWithCustomBuilder> mSparseArray\n @android.annotation.NonNull android.util.SparseIntArray mSparseIntArray\n @java.lang.SuppressWarnings({\"WeakerAccess\"}) @android.annotation.Nullable java.lang.Boolean mNullableBoolean\nclass ParcelAllTheThingsDataClass extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genBuilder=true, genAidl=false, genToString=true)")
@Deprecated
diff --git a/tests/Codegen/src/com/android/codegentest/SampleDataClass.java b/tests/Codegen/src/com/android/codegentest/SampleDataClass.java
index 0fdcf59..c850bf8 100644
--- a/tests/Codegen/src/com/android/codegentest/SampleDataClass.java
+++ b/tests/Codegen/src/com/android/codegentest/SampleDataClass.java
@@ -342,7 +342,7 @@
- // Code below generated by codegen v1.0.13.
+ // Code below generated by codegen v1.0.14.
//
// DO NOT MODIFY!
// CHECKSTYLE:OFF Generated code
@@ -1636,7 +1636,7 @@
/** @see #setLinkAddresses2 */
@DataClass.Generated.Member
- public @NonNull Builder addLinkAddresses2(LinkAddress value) {
+ public @NonNull Builder addLinkAddresses2(@NonNull LinkAddress value) {
// You can refine this method's name by providing item's singular name, e.g.:
// @DataClass.PluralOf("item")) mItems = ...
@@ -1661,7 +1661,7 @@
/** @see #setLinkAddresses */
@DataClass.Generated.Member
- public @NonNull Builder addLinkAddress(LinkAddress value) {
+ public @NonNull Builder addLinkAddress(@NonNull LinkAddress value) {
if (mLinkAddresses == null) setLinkAddresses(new ArrayList<>());
mLinkAddresses.add(value);
return this;
@@ -1872,8 +1872,8 @@
}
@DataClass.Generated(
- time = 1573006402566L,
- codegenVersion = "1.0.13",
+ time = 1574122835009L,
+ codegenVersion = "1.0.14",
sourceFile = "frameworks/base/tests/Codegen/src/com/android/codegentest/SampleDataClass.java",
inputSignatures = "public static final java.lang.String STATE_NAME_UNDEFINED\npublic static final java.lang.String STATE_NAME_ON\npublic static final java.lang.String STATE_NAME_OFF\npublic static final int STATE_UNDEFINED\npublic static final int STATE_ON\npublic static final int STATE_OFF\npublic static final @com.android.codegentest.SampleDataClass.RequestFlags int FLAG_MANUAL_REQUEST\npublic static final @com.android.codegentest.SampleDataClass.RequestFlags int FLAG_COMPATIBILITY_MODE_REQUEST\npublic static final @com.android.codegentest.SampleDataClass.RequestFlags int FLAG_AUGMENTED_REQUEST\nprivate int mNum\nprivate int mNum2\nprivate int mNum4\nprivate @android.annotation.Nullable java.lang.String mName\nprivate @android.annotation.NonNull java.lang.String mName2\nprivate @android.annotation.NonNull java.lang.String mName4\nprivate @android.annotation.Nullable android.view.accessibility.AccessibilityNodeInfo mOtherParcelable\nprivate @com.android.internal.util.DataClass.ParcelWith(com.android.codegentest.MyDateParcelling.class) @android.annotation.NonNull java.util.Date mDate\nprivate @com.android.internal.util.DataClass.ParcelWith(com.android.internal.util.Parcelling.BuiltIn.ForPattern.class) @android.annotation.NonNull java.util.regex.Pattern mPattern\nprivate @android.annotation.NonNull java.util.List<android.net.LinkAddress> mLinkAddresses2\nprivate @com.android.internal.util.DataClass.PluralOf(\"linkAddress\") @android.annotation.NonNull java.util.ArrayList<android.net.LinkAddress> mLinkAddresses\nprivate @android.annotation.Nullable android.net.LinkAddress[] mLinkAddresses4\nprivate @com.android.codegentest.SampleDataClass.StateName @android.annotation.NonNull java.lang.String mStateName\nprivate @com.android.codegentest.SampleDataClass.RequestFlags int mFlags\nprivate @com.android.codegentest.SampleDataClass.State int mState\npublic @android.annotation.NonNull java.lang.CharSequence charSeq\nprivate final @android.annotation.Nullable android.net.LinkAddress[] mLinkAddresses5\nprivate transient android.net.LinkAddress[] mLinkAddresses6\ntransient int[] mTmpStorage\nprivate @android.annotation.StringRes int mStringRes\nprivate @android.annotation.IntRange(from=0L, to=6L) int mDayOfWeek\nprivate @android.annotation.Size(2L) @android.annotation.NonNull @com.android.internal.util.DataClass.Each @android.annotation.FloatRange(from=0.0) float[] mCoords\nprivate static java.lang.String defaultName4()\nprivate int[] lazyInitTmpStorage()\npublic android.net.LinkAddress[] getLinkAddresses4()\nprivate boolean patternEquals(java.util.regex.Pattern)\nprivate int patternHashCode()\nprivate void onConstructed()\npublic void dump(java.io.PrintWriter)\nclass SampleDataClass extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genBuilder=true, genConstructor=true, genEqualsHashCode=true, genToString=true, genForEachField=true, genSetters=true)")
@Deprecated
diff --git a/tests/Codegen/src/com/android/codegentest/SampleWithCustomBuilder.java b/tests/Codegen/src/com/android/codegentest/SampleWithCustomBuilder.java
index cab477d..2de848c 100644
--- a/tests/Codegen/src/com/android/codegentest/SampleWithCustomBuilder.java
+++ b/tests/Codegen/src/com/android/codegentest/SampleWithCustomBuilder.java
@@ -85,7 +85,7 @@
- // Code below generated by codegen v1.0.13.
+ // Code below generated by codegen v1.0.14.
//
// DO NOT MODIFY!
// CHECKSTYLE:OFF Generated code
@@ -253,8 +253,8 @@
}
@DataClass.Generated(
- time = 1573006403628L,
- codegenVersion = "1.0.13",
+ time = 1574122835982L,
+ codegenVersion = "1.0.14",
sourceFile = "frameworks/base/tests/Codegen/src/com/android/codegentest/SampleWithCustomBuilder.java",
inputSignatures = " long delayAmount\n @android.annotation.NonNull java.util.concurrent.TimeUnit delayUnit\n long creationTimestamp\nprivate static java.util.concurrent.TimeUnit unparcelDelayUnit(android.os.Parcel)\nprivate void parcelDelayUnit(android.os.Parcel,int)\nclass SampleWithCustomBuilder extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genBuilder=true, genAidl=false, genToString=true)\nabstract com.android.codegentest.SampleWithCustomBuilder.Builder setDelayAmount(long)\npublic abstract com.android.codegentest.SampleWithCustomBuilder.Builder setDelayUnit(java.util.concurrent.TimeUnit)\npublic com.android.codegentest.SampleWithCustomBuilder.Builder setDelay(long,java.util.concurrent.TimeUnit)\nclass BaseBuilder extends java.lang.Object implements []")
@Deprecated
diff --git a/tests/Codegen/src/com/android/codegentest/SampleWithNestedDataClasses.java b/tests/Codegen/src/com/android/codegentest/SampleWithNestedDataClasses.java
index 6190085..0deffe4 100644
--- a/tests/Codegen/src/com/android/codegentest/SampleWithNestedDataClasses.java
+++ b/tests/Codegen/src/com/android/codegentest/SampleWithNestedDataClasses.java
@@ -36,7 +36,7 @@
- // Code below generated by codegen v1.0.13.
+ // Code below generated by codegen v1.0.14.
//
// DO NOT MODIFY!
// CHECKSTYLE:OFF Generated code
@@ -135,8 +135,8 @@
};
@DataClass.Generated(
- time = 1573006408903L,
- codegenVersion = "1.0.13",
+ time = 1574122840588L,
+ codegenVersion = "1.0.14",
sourceFile = "frameworks/base/tests/Codegen/src/com/android/codegentest/SampleWithNestedDataClasses.java",
inputSignatures = " @android.annotation.NonNull java.lang.String mBar\nclass NestedDataClass extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true)")
@Deprecated
@@ -160,7 +160,7 @@
- // Code below generated by codegen v1.0.13.
+ // Code below generated by codegen v1.0.14.
//
// DO NOT MODIFY!
// CHECKSTYLE:OFF Generated code
@@ -259,8 +259,8 @@
};
@DataClass.Generated(
- time = 1573006408912L,
- codegenVersion = "1.0.13",
+ time = 1574122840597L,
+ codegenVersion = "1.0.14",
sourceFile = "frameworks/base/tests/Codegen/src/com/android/codegentest/SampleWithNestedDataClasses.java",
inputSignatures = " @android.annotation.NonNull long mBaz2\nclass NestedDataClass3 extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true)")
@Deprecated
@@ -274,7 +274,7 @@
- // Code below generated by codegen v1.0.13.
+ // Code below generated by codegen v1.0.14.
//
// DO NOT MODIFY!
// CHECKSTYLE:OFF Generated code
@@ -373,8 +373,8 @@
};
@DataClass.Generated(
- time = 1573006408917L,
- codegenVersion = "1.0.13",
+ time = 1574122840608L,
+ codegenVersion = "1.0.14",
sourceFile = "frameworks/base/tests/Codegen/src/com/android/codegentest/SampleWithNestedDataClasses.java",
inputSignatures = " @android.annotation.NonNull java.lang.String mBaz\nclass NestedDataClass2 extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true)")
@Deprecated
diff --git a/tests/Codegen/src/com/android/codegentest/StaleDataclassDetectorFalsePositivesTest.java b/tests/Codegen/src/com/android/codegentest/StaleDataclassDetectorFalsePositivesTest.java
index 5a960d7..712722b 100644
--- a/tests/Codegen/src/com/android/codegentest/StaleDataclassDetectorFalsePositivesTest.java
+++ b/tests/Codegen/src/com/android/codegentest/StaleDataclassDetectorFalsePositivesTest.java
@@ -51,7 +51,7 @@
- // Code below generated by codegen v1.0.13.
+ // Code below generated by codegen v1.0.14.
//
// DO NOT MODIFY!
// CHECKSTYLE:OFF Generated code
@@ -65,8 +65,8 @@
@DataClass.Generated(
- time = 1573006407900L,
- codegenVersion = "1.0.13",
+ time = 1574122839646L,
+ codegenVersion = "1.0.14",
sourceFile = "frameworks/base/tests/Codegen/src/com/android/codegentest/StaleDataclassDetectorFalsePositivesTest.java",
inputSignatures = "public @android.annotation.NonNull java.lang.String someMethod(int)\nclass StaleDataclassDetectorFalsePositivesTest extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genConstructor=false, genBuilder=false)")
@Deprecated
diff --git a/tools/codegen/src/com/android/codegen/ClassPrinter.kt b/tools/codegen/src/com/android/codegen/ClassPrinter.kt
index a4fd374..c7c80ba 100644
--- a/tools/codegen/src/com/android/codegen/ClassPrinter.kt
+++ b/tools/codegen/src/com/android/codegen/ClassPrinter.kt
@@ -164,7 +164,13 @@
getSuppressedMembers(classAst)
}
val builderSuppressedMembers by lazy {
- getSuppressedMembers(customBaseBuilderAst)
+ getSuppressedMembers(customBaseBuilderAst) + suppressedMembers.mapNotNull {
+ if (it.startsWith("$CANONICAL_BUILDER_CLASS.")) {
+ it.removePrefix("$CANONICAL_BUILDER_CLASS.")
+ } else {
+ null
+ }
+ }
}
private fun getSuppressedMembers(clazz: ClassOrInterfaceDeclaration?): List<String> {
diff --git a/tools/codegen/src/com/android/codegen/Generators.kt b/tools/codegen/src/com/android/codegen/Generators.kt
index dc1f4c5..8fe243f 100644
--- a/tools/codegen/src/com/android/codegen/Generators.kt
+++ b/tools/codegen/src/com/android/codegen/Generators.kt
@@ -270,7 +270,7 @@
private fun ClassPrinter.generateBuilderMethod(
defVisibility: String,
name: String,
- ParamAnnotations: String? = null,
+ paramAnnotations: String? = null,
paramTypes: List<String>,
paramNames: List<String> = listOf("value"),
genJavadoc: ClassPrinter.() -> Unit,
@@ -292,8 +292,12 @@
+GENERATED_MEMBER_HEADER
if (providedMethod?.isAbstract == true) +"@Override"
if (!Annotations.isNullOrEmpty()) +Annotations
- "$visibility @$NonNull $ReturnType $name(${if_(!ParamAnnotations.isNullOrEmpty(), "$ParamAnnotations ")}${
- paramTypes.zip(paramNames).joinToString(", ") { (Type, paramName) -> "$Type $paramName" }
+ val ParamAnnotations = if (!paramAnnotations.isNullOrEmpty()) "$paramAnnotations " else ""
+
+ "$visibility @$NonNull $ReturnType $name(${
+ paramTypes.zip(paramNames).joinToString(", ") { (Type, paramName) ->
+ "$ParamAnnotations$Type $paramName"
+ }
})" {
genBody()
}
@@ -311,7 +315,7 @@
generateBuilderMethod(
name = setterName,
defVisibility = visibility,
- ParamAnnotations = annotationsNoInternal.joinToString(" "),
+ paramAnnotations = annotationsNoInternal.joinToString(" "),
paramTypes = listOf(SetterParamType),
genJavadoc = { generateFieldJavadoc() }) {
+"checkNotUsed();"
@@ -333,6 +337,7 @@
generateBuilderMethod(
name = adderName,
defVisibility = visibility,
+ paramAnnotations = "@$NonNull",
paramTypes = listOf(FieldInnerType),
genJavadoc = { +javadocSeeSetter }) {
@@ -347,6 +352,7 @@
generateBuilderMethod(
name = adderName,
defVisibility = visibility,
+ paramAnnotations = "@$NonNull",
paramTypes = fieldTypeGenegicArgs,
paramNames = listOf("key", "value"),
genJavadoc = { +javadocSeeSetter }) {
diff --git a/tools/codegen/src/com/android/codegen/SharedConstants.kt b/tools/codegen/src/com/android/codegen/SharedConstants.kt
index 85c832f..74c86f4 100644
--- a/tools/codegen/src/com/android/codegen/SharedConstants.kt
+++ b/tools/codegen/src/com/android/codegen/SharedConstants.kt
@@ -1,7 +1,7 @@
package com.android.codegen
const val CODEGEN_NAME = "codegen"
-const val CODEGEN_VERSION = "1.0.13"
+const val CODEGEN_VERSION = "1.0.14"
const val CANONICAL_BUILDER_CLASS = "Builder"
const val BASE_BUILDER_CLASS = "BaseBuilder"
diff --git a/tools/stats_log_api_gen/main.cpp b/tools/stats_log_api_gen/main.cpp
index f62fef0..18e2da3 100644
--- a/tools/stats_log_api_gen/main.cpp
+++ b/tools/stats_log_api_gen/main.cpp
@@ -1309,7 +1309,7 @@
fprintf(out, " write_non_chained(code");
for (int argIndex = 1; argIndex <= argIndexMax; argIndex++) {
if (argIndex == attributionArg) {
- fprintf(out, ", ws.get(i), ws.getName(i)");
+ fprintf(out, ", ws.getUid(i), ws.getPackageName(i)");
} else {
fprintf(out, ", arg%d", argIndex);
}
@@ -1318,7 +1318,7 @@
fprintf(out, " }\n"); // close for-loop
// write() component.
- fprintf(out, " ArrayList<WorkSource.WorkChain> workChains = ws.getWorkChains();\n");
+ fprintf(out, " List<WorkSource.WorkChain> workChains = ws.getWorkChains();\n");
fprintf(out, " if (workChains != null) {\n");
fprintf(out, " for (WorkSource.WorkChain wc : workChains) {\n");
fprintf(out, " write(code");
@@ -1407,7 +1407,7 @@
fprintf(out, "\n");
fprintf(out, "import android.os.WorkSource;\n");
fprintf(out, "import android.util.SparseArray;\n");
- fprintf(out, "import java.util.ArrayList;\n");
+ fprintf(out, "import java.util.List;\n");
fprintf(out, "\n");
fprintf(out, "\n");
fprintf(out, "/**\n");
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 56f152e..6c2a08c 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -4327,7 +4327,7 @@
if (ws == null) {
mWorkSource = null;
} else {
- ws.clearNames();
+ ws = ws.withoutNames();
if (mWorkSource == null) {
changed = mWorkSource != null;
mWorkSource = new WorkSource(ws);