diff --git a/core/api/current.txt b/core/api/current.txt index 7e6ab7c2d7ddc..310e95990b85d 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -10325,6 +10325,7 @@ package android.content { method @Deprecated public abstract void clearWallpaper() throws java.io.IOException; method @NonNull public android.content.Context createAttributionContext(@Nullable String); method public abstract android.content.Context createConfigurationContext(@NonNull android.content.res.Configuration); + method @NonNull public android.content.Context createContext(@NonNull android.content.ContextParams); method public abstract android.content.Context createContextForSplit(String) throws android.content.pm.PackageManager.NameNotFoundException; method public abstract android.content.Context createDeviceProtectedStorageContext(); method public abstract android.content.Context createDisplayContext(@NonNull android.view.Display); @@ -10546,6 +10547,19 @@ package android.content { field public static final String WINDOW_SERVICE = "window"; } + public final class ContextParams { + method @Nullable public String getAttributionTag(); + method @Nullable public String getReceiverAttributionTag(); + method @Nullable public String getReceiverPackage(); + } + + public static final class ContextParams.Builder { + ctor public ContextParams.Builder(); + method @NonNull public android.content.ContextParams build(); + method @NonNull public android.content.ContextParams.Builder setAttributionTag(@NonNull String); + method @NonNull public android.content.ContextParams.Builder setReceiverPackage(@NonNull String, @Nullable String); + } + public class ContextWrapper extends android.content.Context { ctor public ContextWrapper(android.content.Context); method protected void attachBaseContext(android.content.Context); diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java index bc798136f2e3f..fd56c449012f9 100644 --- a/core/java/android/app/ContextImpl.java +++ b/core/java/android/app/ContextImpl.java @@ -24,6 +24,7 @@ import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.compat.annotation.UnsupportedAppUsage; +import android.content.ContextParams; import android.content.AutofillOptions; import android.content.BroadcastReceiver; import android.content.ComponentName; @@ -2606,6 +2607,12 @@ class ContextImpl extends Context { compatInfo, mClassLoader, loaders); } + @NonNull + @Override + public Context createContext(@NonNull ContextParams contextParams) { + return this; + } + @Override public @NonNull Context createAttributionContext(@Nullable String attributionTag) { return new ContextImpl(this, mMainThread, mPackageInfo, attributionTag, mSplitName, diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index 02e86cd4a863f..48754cccfe0d7 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -6376,6 +6376,19 @@ public abstract class Context { throw new RuntimeException("Not implemented. Must override in a subclass."); } + /** + * Creates a context with specific properties and behaviors. + * + * @param contextParams Parameters for how the new context should behave. + * @return A context with the specified behaviors. + * + * @see ContextParams + */ + @NonNull + public Context createContext(@NonNull ContextParams contextParams) { + throw new RuntimeException("Not implemented. Must override in a subclass."); + } + /** * Return a new Context object for the current Context but attribute to a different tag. * In complex apps attribution tagging can be used to distinguish between separate logical diff --git a/core/java/android/content/ContextParams.java b/core/java/android/content/ContextParams.java new file mode 100644 index 0000000000000..16128a650c123 --- /dev/null +++ b/core/java/android/content/ContextParams.java @@ -0,0 +1,121 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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; + +import android.annotation.NonNull; +import android.annotation.Nullable; + +/** + * This class represents rules around how a context being created via + * {@link Context#createContext} should behave. + * + *
One of the dimensions to customize is how permissions should behave. + * For example, you can specify how permission accesses from a context should + * be attributed in the platform's permission tracking system. + * + *
The two main types of attribution are: against an attribution tag which + * is an arbitrary string your app specifies for the purposes of tracking permission + * accesses from a given portion of your app; against another package and optionally + * its attribution tag if you are accessing the data on behalf of another app and + * you will be passing that data to this app. Both attributions are not mutually + * exclusive. + * + *
For example if you have a feature "foo" in your app which accesses + * permissions on behalf of app "foo.bar.baz" with feature "bar" you need to + * create a context like this: + * + *
+ * context.createContext(new ContextParams.Builder()
+ * .setAttributionTag("foo")
+ * .setReceiverPackage("foo.bar.baz", "bar")
+ * .build())
+ *
+ *
+ * @see Context#createContext(ContextParams)
+ */
+public final class ContextParams {
+
+ private ContextParams() {
+ /* hide ctor */
+ }
+
+ /**
+ * @return The attribution tag.
+ */
+ @Nullable
+ public String getAttributionTag() {
+ return null;
+ }
+
+ /**
+ * @return The receiving package.
+ */
+ @Nullable
+ public String getReceiverPackage() {
+ return null;
+ }
+
+ /**
+ * @return The receiving package's attribution tag.
+ */
+ @Nullable
+ public String getReceiverAttributionTag() {
+ return null;
+ }
+
+ /**
+ * Builder for creating a {@link ContextParams}.
+ */
+ public static final class Builder {
+
+ /**
+ * Sets an attribution tag against which to track permission accesses.
+ *
+ * @param attributionTag The attribution tag.
+ * @return This builder.
+ */
+ @NonNull
+ public Builder setAttributionTag(@NonNull String attributionTag) {
+ return this;
+ }
+
+ /**
+ * Sets the package and its optional attribution tag that would be receiving
+ * the permission protected data.
+ *
+ * @param packageName The package name receiving the permission protected data.
+ * @param attributionTag An attribution tag of the receiving package.
+ * @return This builder.
+ */
+ @NonNull
+ public Builder setReceiverPackage(@NonNull String packageName,
+ @Nullable String attributionTag) {
+ return this;
+ }
+
+ /**
+ * Creates a new instance. You need to either specify an attribution tag
+ * or a receiver package or both.
+ *
+ * @return The new instance.
+ */
+ @NonNull
+ public ContextParams build() {
+ return new ContextParams();
+ }
+ }
+}