1 /*
2  * Copyright 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package androidx.remotecallback;
18 
19 import static androidx.remotecallback.ProviderRelayReceiver.ACTION_PROVIDER_RELAY;
20 import static androidx.remotecallback.RemoteCallback.EXTRA_METHOD;
21 import static androidx.remotecallback.RemoteCallback.TYPE_PROVIDER;
22 
23 import android.content.ComponentName;
24 import android.content.ContentProvider;
25 import android.content.Context;
26 import android.content.Intent;
27 import android.content.pm.ProviderInfo;
28 import android.os.Bundle;
29 
30 import androidx.annotation.RestrictTo;
31 
32 import org.jspecify.annotations.NonNull;
33 import org.jspecify.annotations.Nullable;
34 
35 /**
36  * Version of ContentProvider that can be used as a {@link CallbackReceiver}.
37  *
38  * Be sure to call the super of {@link #call} when unhandled to ensure
39  * callbacks are triggered.
40  *
41  * @param <T> Should be specified as the root class (e.g. class X extends
42  *           ContentProviderWithCallbacks\<X>)
43  *
44  * @deprecated Slice framework has been deprecated, it will not receive any updates moving
45  * forward. If you are looking for a framework that handles communication across apps,
46  * consider using {@link android.app.appsearch.AppSearchManager}.
47  */
48 @Deprecated
49 @SuppressWarnings("HiddenSuperclass")
50 public abstract class ContentProviderWithCallbacks<T extends ContentProviderWithCallbacks> extends
51         ContentProvider implements CallbackReceiver<T>, CallbackBase<T> {
52 
53     String mAuthority;
54 
55     @Override
attachInfo(Context context, ProviderInfo info)56     public void attachInfo(Context context, ProviderInfo info) {
57         super.attachInfo(context, info);
58         mAuthority = info.authority;
59     }
60 
61     @Override
call(@onNull String method, @Nullable String arg, @Nullable Bundle extras)62     public @Nullable Bundle call(@NonNull String method, @Nullable String arg,
63             @Nullable Bundle extras) {
64         if (ProviderRelayReceiver.METHOD_PROVIDER_CALLBACK.equals(method)) {
65             CallbackHandlerRegistry.sInstance.invokeCallback(getContext(), this, extras);
66             return null;
67         }
68         return super.call(method, arg, extras);
69     }
70 
71     @Override
createRemoteCallback(@onNull Context context)72     public @NonNull T createRemoteCallback(@NonNull Context context) {
73         return CallbackHandlerRegistry.sInstance.getAndResetStub(getClass(), context, mAuthority);
74     }
75 
76     /**
77      */
78     @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
79     @Override
toRemoteCallback(@onNull Class<T> cls, @NonNull Context context, @Nullable String authority, @NonNull Bundle args, @NonNull String method)80     public @NonNull RemoteCallback toRemoteCallback(@NonNull Class<T> cls, @NonNull Context context,
81             @Nullable String authority,
82             @NonNull Bundle args, @NonNull String method) {
83 
84         Intent intent = new Intent(ACTION_PROVIDER_RELAY);
85         intent.setComponent(new ComponentName(context.getPackageName(),
86                 ProviderRelayReceiver.class.getName()));
87         args.putString(EXTRA_METHOD, method);
88         args.putString(ProviderRelayReceiver.EXTRA_AUTHORITY, authority);
89         intent.putExtras(args);
90         return new RemoteCallback(context, TYPE_PROVIDER, intent, cls.getName(), args);
91     }
92 }
93