1 /*
2  * Copyright (C) 2021 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 com.android.systemui.people;
18 
19 import android.content.ContentProvider;
20 import android.content.ContentValues;
21 import android.content.Context;
22 import android.content.pm.PackageManager;
23 import android.content.pm.ProviderInfo;
24 import android.database.Cursor;
25 import android.net.Uri;
26 import android.os.Binder;
27 import android.os.Bundle;
28 import android.os.UserHandle;
29 import android.util.Log;
30 import android.widget.RemoteViews;
31 
32 import com.android.systemui.SystemUIAppComponentFactoryBase.ContextAvailableCallback;
33 import com.android.systemui.SystemUIAppComponentFactoryBase.ContextInitializer;
34 import com.android.systemui.people.widget.PeopleSpaceWidgetManager;
35 import com.android.systemui.shared.system.PeopleProviderUtils;
36 
37 import javax.inject.Inject;
38 
39 /** API that returns a People Tile preview. */
40 public class PeopleProvider extends ContentProvider implements
41         ContextInitializer {
42     private static final String TAG = "PeopleProvider";
43     private static final boolean DEBUG = PeopleSpaceUtils.DEBUG;
44     private static final String EMPTY_STRING = "";
45     private ContextAvailableCallback mCallback;
46 
47     @Inject
48     PeopleSpaceWidgetManager mPeopleSpaceWidgetManager;
49 
50     @Override
call(String method, String arg, Bundle extras)51     public Bundle call(String method, String arg, Bundle extras) {
52         if (!doesCallerHavePermission()) {
53             String callingPackage = getCallingPackage();
54             Log.w(TAG, "API not accessible to calling package: " + callingPackage);
55             throw new SecurityException("API not accessible to calling package: " + callingPackage);
56         }
57         if (!PeopleProviderUtils.GET_PEOPLE_TILE_PREVIEW_METHOD.equals(method)) {
58             Log.w(TAG, "Invalid method");
59             throw new IllegalArgumentException("Invalid method");
60         }
61 
62         if (extras == null) {
63             Log.w(TAG, "Extras can't be null");
64             throw new IllegalArgumentException("Extras can't be null");
65         }
66 
67         String shortcutId = extras.getString(
68                 PeopleProviderUtils.EXTRAS_KEY_SHORTCUT_ID, EMPTY_STRING);
69         String packageName = extras.getString(
70                 PeopleProviderUtils.EXTRAS_KEY_PACKAGE_NAME, EMPTY_STRING);
71         UserHandle userHandle = extras.getParcelable(
72                 PeopleProviderUtils.EXTRAS_KEY_USER_HANDLE);
73         if (shortcutId.isEmpty()) {
74             Log.w(TAG, "Invalid shortcut id");
75             throw new IllegalArgumentException("Invalid shortcut id");
76         }
77 
78         if (packageName.isEmpty()) {
79             Log.w(TAG, "Invalid package name");
80             throw new IllegalArgumentException("Invalid package name");
81         }
82         if (userHandle == null) {
83             Log.w(TAG, "Null user handle");
84             throw new IllegalArgumentException("Null user handle");
85         }
86 
87         if (mPeopleSpaceWidgetManager == null) {
88             Log.e(TAG, "Could not initialize people widget manager");
89             return null;
90         }
91         RemoteViews view = mPeopleSpaceWidgetManager.getPreview(shortcutId, userHandle, packageName,
92                 extras);
93         if (view == null) {
94             if (DEBUG) Log.d(TAG, "No preview available for shortcutId: " + shortcutId);
95             return null;
96         }
97         final Bundle bundle = new Bundle();
98         bundle.putParcelable(PeopleProviderUtils.RESPONSE_KEY_REMOTE_VIEWS, view);
99         return bundle;
100     }
101 
doesCallerHavePermission()102     private boolean doesCallerHavePermission() {
103         return getContext().checkPermission(
104                 PeopleProviderUtils.GET_PEOPLE_TILE_PREVIEW_PERMISSION,
105                 Binder.getCallingPid(), Binder.getCallingUid())
106                 == PackageManager.PERMISSION_GRANTED;
107     }
108 
109     @Override
onCreate()110     public boolean onCreate() {
111         return true;
112     }
113 
114     @Override
query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder)115     public Cursor query(Uri uri, String[] projection, String selection,
116             String[] selectionArgs, String sortOrder) {
117         throw new IllegalArgumentException("Invalid method");
118     }
119 
120     @Override
getType(Uri uri)121     public String getType(Uri uri) {
122         throw new IllegalArgumentException("Invalid method");
123     }
124 
125     @Override
insert(Uri uri, ContentValues initialValues)126     public Uri insert(Uri uri, ContentValues initialValues) {
127         throw new IllegalArgumentException("Invalid method");
128     }
129 
130     @Override
delete(Uri uri, String selection, String[] selectionArgs)131     public int delete(Uri uri, String selection, String[] selectionArgs) {
132         throw new IllegalArgumentException("Invalid method");
133     }
134 
135     @Override
update(Uri uri, ContentValues values, String selection, String[] selectionArgs)136     public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
137         throw new IllegalArgumentException("Invalid method");
138     }
139 
140     @Override
attachInfo(Context context, ProviderInfo info)141     public void attachInfo(Context context, ProviderInfo info) {
142         mCallback.onContextAvailable(context);
143         super.attachInfo(context, info);
144     }
145 
146     @Override
setContextAvailableCallback( ContextAvailableCallback callback)147     public void setContextAvailableCallback(
148             ContextAvailableCallback callback) {
149         mCallback = callback;
150     }
151 }
152 
153