Loading core/res/AndroidManifest.xml +3 −0 Original line number Diff line number Diff line Loading @@ -5477,6 +5477,9 @@ <permission android:name="android.permission.SIGNAL_REBOOT_READINESS" android:protectionLevel="signature|privileged" /> <!-- @hide Allows an application to get a People Tile preview for a given shortcut. --> <permission android:name="android.permission.GET_PEOPLE_TILE_PREVIEW" android:protectionLevel="signature|recents" /> <!-- Attribution for Geofencing service. --> <attribution android:tag="GeofencingService" android:label="@string/geofencing_service"/> Loading packages/SystemUI/AndroidManifest.xml +8 −0 Original line number Diff line number Diff line Loading @@ -600,6 +600,14 @@ android:permission="android.permission.BIND_REMOTEVIEWS" android:exported="false" /> <!-- ContentProvider that returns a People Tile preview for a given shortcut --> <provider android:name="com.android.systemui.people.PeopleProvider" android:authorities="com.android.systemui.people.PeopleProvider" android:exported="true" android:permission="android.permission.GET_PEOPLE_TILE_PREVIEW"> </provider> <!-- a gallery of delicious treats --> <service android:name=".DessertCaseDream" Loading packages/SystemUI/shared/src/com/android/systemui/shared/system/PeopleProviderUtils.java 0 → 100644 +76 −0 Original line number Diff line number Diff line /* * 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 com.android.systemui.shared.system; /** * These strings are part of the {@link com.android.systemui.people.PeopleProvider} API * contract. The API returns a People Tile preview that can be displayed by calling packages. * The provider is part of the SystemUI service, and the strings live here for shared access with * Launcher (caller). */ public class PeopleProviderUtils { /** * ContentProvider URI scheme. * @hide */ public static final String PEOPLE_PROVIDER_SCHEME = "content://"; /** * ContentProvider URI authority. * @hide */ public static final String PEOPLE_PROVIDER_AUTHORITY = "com.android.systemui.people.PeopleProvider"; /** * Method name for getting People Tile preview. * @hide */ public static final String GET_PEOPLE_TILE_PREVIEW_METHOD = "get_people_tile_preview"; /** * Extras bundle key specifying shortcut Id of the People Tile preview requested. * @hide */ public static final String EXTRAS_KEY_SHORTCUT_ID = "shortcut_id"; /** * Extras bundle key specifying package name of the People Tile preview requested. * @hide */ public static final String EXTRAS_KEY_PACKAGE_NAME = "package_name"; /** * Extras bundle key specifying {@code UserHandle} of the People Tile preview requested. * @hide */ public static final String EXTRAS_KEY_USER_HANDLE = "user_handle"; /** * Response bundle key to access the returned People Tile preview. * @hide */ public static final String RESPONSE_KEY_REMOTE_VIEWS = "remote_views"; /** * Name of the permission needed to get a People Tile preview for a given conversation shortcut. * @hide */ public static final String GET_PEOPLE_TILE_PREVIEW_PERMISSION = "android.permission.GET_PEOPLE_TILE_PREVIEW"; } packages/SystemUI/src/com/android/systemui/people/PeopleProvider.java 0 → 100644 +157 −0 Original line number Diff line number Diff line /* * 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 com.android.systemui.people; import android.app.people.ConversationChannel; import android.app.people.IPeopleManager; import android.app.people.PeopleSpaceTile; import android.content.ContentProvider; import android.content.ContentValues; import android.content.Context; import android.content.pm.LauncherApps; import android.content.pm.PackageManager; import android.database.Cursor; import android.net.Uri; import android.os.Binder; import android.os.Bundle; import android.os.ServiceManager; import android.os.UserHandle; import android.util.Log; import android.widget.RemoteViews; import com.android.systemui.shared.system.PeopleProviderUtils; /** API that returns a People Tile preview. */ public class PeopleProvider extends ContentProvider { LauncherApps mLauncherApps; IPeopleManager mPeopleManager; private static final String TAG = "PeopleProvider"; private static final boolean DEBUG = PeopleSpaceUtils.DEBUG; private static final String EMPTY_STRING = ""; @Override public Bundle call(String method, String arg, Bundle extras) { if (!doesCallerHavePermission()) { String callingPackage = getCallingPackage(); Log.w(TAG, "API not accessible to calling package: " + callingPackage); throw new SecurityException("API not accessible to calling package: " + callingPackage); } if (!PeopleProviderUtils.GET_PEOPLE_TILE_PREVIEW_METHOD.equals(method)) { Log.w(TAG, "Invalid method"); throw new IllegalArgumentException("Invalid method"); } // If services are not set as mocks in tests, fetch them now. mPeopleManager = mPeopleManager != null ? mPeopleManager : IPeopleManager.Stub.asInterface( ServiceManager.getService(Context.PEOPLE_SERVICE)); mLauncherApps = mLauncherApps != null ? mLauncherApps : getContext().getSystemService(LauncherApps.class); if (mPeopleManager == null || mLauncherApps == null) { Log.w(TAG, "Null system managers"); return null; } if (extras == null) { Log.w(TAG, "Extras can't be null"); throw new IllegalArgumentException("Extras can't be null"); } String shortcutId = extras.getString( PeopleProviderUtils.EXTRAS_KEY_SHORTCUT_ID, EMPTY_STRING); String packageName = extras.getString( PeopleProviderUtils.EXTRAS_KEY_PACKAGE_NAME, EMPTY_STRING); UserHandle userHandle = extras.getParcelable( PeopleProviderUtils.EXTRAS_KEY_USER_HANDLE); if (shortcutId.isEmpty()) { Log.w(TAG, "Invalid shortcut id"); throw new IllegalArgumentException("Invalid shortcut id"); } if (packageName.isEmpty()) { Log.w(TAG, "Invalid package name"); throw new IllegalArgumentException("Invalid package name"); } if (userHandle == null) { Log.w(TAG, "Null user handle"); throw new IllegalArgumentException("Null user handle"); } ConversationChannel channel; try { channel = mPeopleManager.getConversation( packageName, userHandle.getIdentifier(), shortcutId); } catch (Exception e) { Log.w(TAG, "Exception getting tiles: " + e); return null; } PeopleSpaceTile tile = PeopleSpaceUtils.getTile(channel, mLauncherApps); if (tile == null) { if (DEBUG) Log.i(TAG, "No tile was returned"); return null; } if (DEBUG) Log.i(TAG, "Returning tile preview for shortcutId: " + shortcutId); RemoteViews view = PeopleSpaceUtils.createRemoteViews(getContext(), tile, 0); final Bundle bundle = new Bundle(); bundle.putParcelable(PeopleProviderUtils.RESPONSE_KEY_REMOTE_VIEWS, view); return bundle; } private boolean doesCallerHavePermission() { return getContext().checkPermission( PeopleProviderUtils.GET_PEOPLE_TILE_PREVIEW_PERMISSION, Binder.getCallingPid(), Binder.getCallingUid()) == PackageManager.PERMISSION_GRANTED; } @Override public boolean onCreate() { return true; } @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { throw new IllegalArgumentException("Invalid method"); } @Override public String getType(Uri uri) { throw new IllegalArgumentException("Invalid method"); } @Override public Uri insert(Uri uri, ContentValues initialValues) { throw new IllegalArgumentException("Invalid method"); } @Override public int delete(Uri uri, String selection, String[] selectionArgs) { throw new IllegalArgumentException("Invalid method"); } @Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { throw new IllegalArgumentException("Invalid method"); } } packages/SystemUI/src/com/android/systemui/people/PeopleSpaceUtils.java +23 −6 Original line number Diff line number Diff line Loading @@ -49,6 +49,7 @@ import android.provider.ContactsContract; import android.provider.Settings; import android.service.notification.ConversationChannelWrapper; import android.service.notification.StatusBarNotification; import android.text.TextUtils; import android.util.Log; import android.view.View; import android.widget.RemoteViews; Loading Loading @@ -438,7 +439,7 @@ public class PeopleSpaceUtils { } /** Creates a {@link RemoteViews} for {@code tile}. */ private static RemoteViews createRemoteViews(Context context, public static RemoteViews createRemoteViews(Context context, PeopleSpaceTile tile, int appWidgetId) { RemoteViews views; if (tile.getNotificationKey() != null) { Loading @@ -455,6 +456,9 @@ public class PeopleSpaceUtils { PeopleSpaceTile tile, int appWidgetId) { try { views.setTextViewText(R.id.name, tile.getUserName().toString()); views.setImageViewIcon(R.id.person_icon, tile.getUserIcon()); views.setBoolean(R.id.content_background, "setClipToOutline", true); views.setImageViewBitmap( R.id.package_icon, PeopleSpaceUtils.convertDrawableToBitmap( Loading @@ -462,8 +466,6 @@ public class PeopleSpaceUtils { tile.getPackageName()) ) ); views.setImageViewIcon(R.id.person_icon, tile.getUserIcon()); views.setBoolean(R.id.content_background, "setClipToOutline", true); Intent activityIntent = new Intent(context, LaunchConversationActivity.class); activityIntent.addFlags( Loading Loading @@ -612,6 +614,22 @@ public class PeopleSpaceUtils { .collect(Collectors.toList()); } /** Returns {@code PeopleSpaceTile} based on provided {@ConversationChannel}. */ public static PeopleSpaceTile getTile(ConversationChannel channel, LauncherApps launcherApps) { if (channel == null) { Log.i(TAG, "ConversationChannel is null"); return null; } PeopleSpaceTile tile = new PeopleSpaceTile.Builder(channel, launcherApps).build(); if (!PeopleSpaceUtils.shouldKeepConversation(tile)) { Log.i(TAG, "PeopleSpaceTile is not valid"); return null; } return tile; } /** Returns the last interaction time with the user specified by {@code PeopleSpaceTile}. */ private static Long getLastInteraction(IPeopleManager peopleManager, PeopleSpaceTile tile) { Loading Loading @@ -701,7 +719,7 @@ public class PeopleSpaceUtils { * </li> */ public static boolean shouldKeepConversation(PeopleSpaceTile tile) { return tile != null && tile.getUserName().length() != 0; return tile != null && !TextUtils.isEmpty(tile.getUserName()); } private static boolean hasBirthdayStatus(PeopleSpaceTile tile, Context context) { Loading Loading @@ -792,8 +810,7 @@ public class PeopleSpaceUtils { private static void updateAppWidgetOptionsAndView(AppWidgetManager appWidgetManager, Context context, int appWidgetId, PeopleSpaceTile tile) { updateAppWidgetOptions(appWidgetManager, appWidgetId, tile); RemoteViews views = createRemoteViews(context, tile, appWidgetId); RemoteViews views = createRemoteViews(context, tile, appWidgetId); appWidgetManager.updateAppWidget(appWidgetId, views); } Loading Loading
core/res/AndroidManifest.xml +3 −0 Original line number Diff line number Diff line Loading @@ -5477,6 +5477,9 @@ <permission android:name="android.permission.SIGNAL_REBOOT_READINESS" android:protectionLevel="signature|privileged" /> <!-- @hide Allows an application to get a People Tile preview for a given shortcut. --> <permission android:name="android.permission.GET_PEOPLE_TILE_PREVIEW" android:protectionLevel="signature|recents" /> <!-- Attribution for Geofencing service. --> <attribution android:tag="GeofencingService" android:label="@string/geofencing_service"/> Loading
packages/SystemUI/AndroidManifest.xml +8 −0 Original line number Diff line number Diff line Loading @@ -600,6 +600,14 @@ android:permission="android.permission.BIND_REMOTEVIEWS" android:exported="false" /> <!-- ContentProvider that returns a People Tile preview for a given shortcut --> <provider android:name="com.android.systemui.people.PeopleProvider" android:authorities="com.android.systemui.people.PeopleProvider" android:exported="true" android:permission="android.permission.GET_PEOPLE_TILE_PREVIEW"> </provider> <!-- a gallery of delicious treats --> <service android:name=".DessertCaseDream" Loading
packages/SystemUI/shared/src/com/android/systemui/shared/system/PeopleProviderUtils.java 0 → 100644 +76 −0 Original line number Diff line number Diff line /* * 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 com.android.systemui.shared.system; /** * These strings are part of the {@link com.android.systemui.people.PeopleProvider} API * contract. The API returns a People Tile preview that can be displayed by calling packages. * The provider is part of the SystemUI service, and the strings live here for shared access with * Launcher (caller). */ public class PeopleProviderUtils { /** * ContentProvider URI scheme. * @hide */ public static final String PEOPLE_PROVIDER_SCHEME = "content://"; /** * ContentProvider URI authority. * @hide */ public static final String PEOPLE_PROVIDER_AUTHORITY = "com.android.systemui.people.PeopleProvider"; /** * Method name for getting People Tile preview. * @hide */ public static final String GET_PEOPLE_TILE_PREVIEW_METHOD = "get_people_tile_preview"; /** * Extras bundle key specifying shortcut Id of the People Tile preview requested. * @hide */ public static final String EXTRAS_KEY_SHORTCUT_ID = "shortcut_id"; /** * Extras bundle key specifying package name of the People Tile preview requested. * @hide */ public static final String EXTRAS_KEY_PACKAGE_NAME = "package_name"; /** * Extras bundle key specifying {@code UserHandle} of the People Tile preview requested. * @hide */ public static final String EXTRAS_KEY_USER_HANDLE = "user_handle"; /** * Response bundle key to access the returned People Tile preview. * @hide */ public static final String RESPONSE_KEY_REMOTE_VIEWS = "remote_views"; /** * Name of the permission needed to get a People Tile preview for a given conversation shortcut. * @hide */ public static final String GET_PEOPLE_TILE_PREVIEW_PERMISSION = "android.permission.GET_PEOPLE_TILE_PREVIEW"; }
packages/SystemUI/src/com/android/systemui/people/PeopleProvider.java 0 → 100644 +157 −0 Original line number Diff line number Diff line /* * 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 com.android.systemui.people; import android.app.people.ConversationChannel; import android.app.people.IPeopleManager; import android.app.people.PeopleSpaceTile; import android.content.ContentProvider; import android.content.ContentValues; import android.content.Context; import android.content.pm.LauncherApps; import android.content.pm.PackageManager; import android.database.Cursor; import android.net.Uri; import android.os.Binder; import android.os.Bundle; import android.os.ServiceManager; import android.os.UserHandle; import android.util.Log; import android.widget.RemoteViews; import com.android.systemui.shared.system.PeopleProviderUtils; /** API that returns a People Tile preview. */ public class PeopleProvider extends ContentProvider { LauncherApps mLauncherApps; IPeopleManager mPeopleManager; private static final String TAG = "PeopleProvider"; private static final boolean DEBUG = PeopleSpaceUtils.DEBUG; private static final String EMPTY_STRING = ""; @Override public Bundle call(String method, String arg, Bundle extras) { if (!doesCallerHavePermission()) { String callingPackage = getCallingPackage(); Log.w(TAG, "API not accessible to calling package: " + callingPackage); throw new SecurityException("API not accessible to calling package: " + callingPackage); } if (!PeopleProviderUtils.GET_PEOPLE_TILE_PREVIEW_METHOD.equals(method)) { Log.w(TAG, "Invalid method"); throw new IllegalArgumentException("Invalid method"); } // If services are not set as mocks in tests, fetch them now. mPeopleManager = mPeopleManager != null ? mPeopleManager : IPeopleManager.Stub.asInterface( ServiceManager.getService(Context.PEOPLE_SERVICE)); mLauncherApps = mLauncherApps != null ? mLauncherApps : getContext().getSystemService(LauncherApps.class); if (mPeopleManager == null || mLauncherApps == null) { Log.w(TAG, "Null system managers"); return null; } if (extras == null) { Log.w(TAG, "Extras can't be null"); throw new IllegalArgumentException("Extras can't be null"); } String shortcutId = extras.getString( PeopleProviderUtils.EXTRAS_KEY_SHORTCUT_ID, EMPTY_STRING); String packageName = extras.getString( PeopleProviderUtils.EXTRAS_KEY_PACKAGE_NAME, EMPTY_STRING); UserHandle userHandle = extras.getParcelable( PeopleProviderUtils.EXTRAS_KEY_USER_HANDLE); if (shortcutId.isEmpty()) { Log.w(TAG, "Invalid shortcut id"); throw new IllegalArgumentException("Invalid shortcut id"); } if (packageName.isEmpty()) { Log.w(TAG, "Invalid package name"); throw new IllegalArgumentException("Invalid package name"); } if (userHandle == null) { Log.w(TAG, "Null user handle"); throw new IllegalArgumentException("Null user handle"); } ConversationChannel channel; try { channel = mPeopleManager.getConversation( packageName, userHandle.getIdentifier(), shortcutId); } catch (Exception e) { Log.w(TAG, "Exception getting tiles: " + e); return null; } PeopleSpaceTile tile = PeopleSpaceUtils.getTile(channel, mLauncherApps); if (tile == null) { if (DEBUG) Log.i(TAG, "No tile was returned"); return null; } if (DEBUG) Log.i(TAG, "Returning tile preview for shortcutId: " + shortcutId); RemoteViews view = PeopleSpaceUtils.createRemoteViews(getContext(), tile, 0); final Bundle bundle = new Bundle(); bundle.putParcelable(PeopleProviderUtils.RESPONSE_KEY_REMOTE_VIEWS, view); return bundle; } private boolean doesCallerHavePermission() { return getContext().checkPermission( PeopleProviderUtils.GET_PEOPLE_TILE_PREVIEW_PERMISSION, Binder.getCallingPid(), Binder.getCallingUid()) == PackageManager.PERMISSION_GRANTED; } @Override public boolean onCreate() { return true; } @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { throw new IllegalArgumentException("Invalid method"); } @Override public String getType(Uri uri) { throw new IllegalArgumentException("Invalid method"); } @Override public Uri insert(Uri uri, ContentValues initialValues) { throw new IllegalArgumentException("Invalid method"); } @Override public int delete(Uri uri, String selection, String[] selectionArgs) { throw new IllegalArgumentException("Invalid method"); } @Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { throw new IllegalArgumentException("Invalid method"); } }
packages/SystemUI/src/com/android/systemui/people/PeopleSpaceUtils.java +23 −6 Original line number Diff line number Diff line Loading @@ -49,6 +49,7 @@ import android.provider.ContactsContract; import android.provider.Settings; import android.service.notification.ConversationChannelWrapper; import android.service.notification.StatusBarNotification; import android.text.TextUtils; import android.util.Log; import android.view.View; import android.widget.RemoteViews; Loading Loading @@ -438,7 +439,7 @@ public class PeopleSpaceUtils { } /** Creates a {@link RemoteViews} for {@code tile}. */ private static RemoteViews createRemoteViews(Context context, public static RemoteViews createRemoteViews(Context context, PeopleSpaceTile tile, int appWidgetId) { RemoteViews views; if (tile.getNotificationKey() != null) { Loading @@ -455,6 +456,9 @@ public class PeopleSpaceUtils { PeopleSpaceTile tile, int appWidgetId) { try { views.setTextViewText(R.id.name, tile.getUserName().toString()); views.setImageViewIcon(R.id.person_icon, tile.getUserIcon()); views.setBoolean(R.id.content_background, "setClipToOutline", true); views.setImageViewBitmap( R.id.package_icon, PeopleSpaceUtils.convertDrawableToBitmap( Loading @@ -462,8 +466,6 @@ public class PeopleSpaceUtils { tile.getPackageName()) ) ); views.setImageViewIcon(R.id.person_icon, tile.getUserIcon()); views.setBoolean(R.id.content_background, "setClipToOutline", true); Intent activityIntent = new Intent(context, LaunchConversationActivity.class); activityIntent.addFlags( Loading Loading @@ -612,6 +614,22 @@ public class PeopleSpaceUtils { .collect(Collectors.toList()); } /** Returns {@code PeopleSpaceTile} based on provided {@ConversationChannel}. */ public static PeopleSpaceTile getTile(ConversationChannel channel, LauncherApps launcherApps) { if (channel == null) { Log.i(TAG, "ConversationChannel is null"); return null; } PeopleSpaceTile tile = new PeopleSpaceTile.Builder(channel, launcherApps).build(); if (!PeopleSpaceUtils.shouldKeepConversation(tile)) { Log.i(TAG, "PeopleSpaceTile is not valid"); return null; } return tile; } /** Returns the last interaction time with the user specified by {@code PeopleSpaceTile}. */ private static Long getLastInteraction(IPeopleManager peopleManager, PeopleSpaceTile tile) { Loading Loading @@ -701,7 +719,7 @@ public class PeopleSpaceUtils { * </li> */ public static boolean shouldKeepConversation(PeopleSpaceTile tile) { return tile != null && tile.getUserName().length() != 0; return tile != null && !TextUtils.isEmpty(tile.getUserName()); } private static boolean hasBirthdayStatus(PeopleSpaceTile tile, Context context) { Loading Loading @@ -792,8 +810,7 @@ public class PeopleSpaceUtils { private static void updateAppWidgetOptionsAndView(AppWidgetManager appWidgetManager, Context context, int appWidgetId, PeopleSpaceTile tile) { updateAppWidgetOptions(appWidgetManager, appWidgetId, tile); RemoteViews views = createRemoteViews(context, tile, appWidgetId); RemoteViews views = createRemoteViews(context, tile, appWidgetId); appWidgetManager.updateAppWidget(appWidgetId, views); } Loading