Loading res/values/config.xml +3 −0 Original line number Diff line number Diff line Loading @@ -425,4 +425,7 @@ <string-array name="config_panel_keep_observe_uri" translatable="false"> <item>content://com.android.settings.slices/intent/media_output_indicator</item> </string-array> <!-- Uri to query non-public Slice Uris. --> <string name="config_non_public_slice_query_uri" translatable="false"></string> </resources> src/com/android/settings/search/SettingsSearchIndexablesProvider.java +5 −2 Original line number Diff line number Diff line Loading @@ -61,6 +61,7 @@ import android.util.Log; import androidx.annotation.Nullable; import androidx.slice.SliceViewManager; import com.android.settings.R; import com.android.settings.SettingsActivity; import com.android.settings.dashboard.DashboardFeatureProvider; import com.android.settings.overlay.FeatureFactory; Loading Loading @@ -216,11 +217,13 @@ public class SettingsSearchIndexablesProvider extends SearchIndexablesProvider { public Cursor querySliceUriPairs() { final SliceViewManager manager = SliceViewManager.getInstance(getContext()); final MatrixCursor cursor = new MatrixCursor(SLICE_URI_PAIRS_COLUMNS); final Uri baseUri = new Uri.Builder() final String queryUri = getContext().getString(R.string.config_non_public_slice_query_uri); final Uri baseUri = !TextUtils.isEmpty(queryUri) ? Uri.parse(queryUri) : new Uri.Builder() .scheme(ContentResolver.SCHEME_CONTENT) .authority(SettingsSliceProvider.SLICE_AUTHORITY) .build(); final Uri platformBaseUri = new Uri.Builder() .scheme(ContentResolver.SCHEME_CONTENT) Loading src/com/android/settings/slices/SettingsSliceProvider.java +39 −5 Original line number Diff line number Diff line Loading @@ -20,10 +20,13 @@ import static android.Manifest.permission.READ_SEARCH_INDEXABLES; import android.app.PendingIntent; import android.app.slice.SliceManager; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.PackageManager; import android.net.Uri; import android.os.Binder; import android.os.StrictMode; import android.provider.Settings; import android.provider.SettingsSlicesContract; Loading Loading @@ -265,16 +268,29 @@ public class SettingsSliceProvider extends SliceProvider { @Override public Collection<Uri> onGetSliceDescendants(Uri uri) { final List<Uri> descendants = new ArrayList<>(); final Pair<Boolean, String> pathData = SliceBuilderUtils.getPathData(uri); Uri finalUri = uri; if (isPrivateSlicesNeeded(finalUri)) { descendants.addAll( mSlicesDatabaseAccessor.getSliceUris(finalUri.getAuthority(), false /* isPublicSlice */)); Log.d(TAG, "provide " + descendants.size() + " non-public slices"); finalUri = new Uri.Builder() .scheme(ContentResolver.SCHEME_CONTENT) .authority(finalUri.getAuthority()) .build(); } final Pair<Boolean, String> pathData = SliceBuilderUtils.getPathData(finalUri); if (pathData != null) { // Uri has a full path and will not have any descendants. descendants.add(uri); descendants.add(finalUri); return descendants; } final String authority = uri.getAuthority(); final String path = uri.getPath(); final String authority = finalUri.getAuthority(); final String path = finalUri.getPath(); final boolean isPathEmpty = path.isEmpty(); // Path is anything but empty, "action", or "intent". Return empty list. Loading @@ -286,7 +302,7 @@ public class SettingsSliceProvider extends SliceProvider { } // Add all descendants from db with matching authority. descendants.addAll(mSlicesDatabaseAccessor.getSliceUris(authority)); descendants.addAll(mSlicesDatabaseAccessor.getSliceUris(authority, true /*isPublicSlice*/)); if (isPathEmpty && TextUtils.isEmpty(authority)) { // No path nor authority. Return all possible Uris by adding all special slice uri Loading Loading @@ -404,6 +420,24 @@ public class SettingsSliceProvider extends SliceProvider { return set; } @VisibleForTesting boolean isPrivateSlicesNeeded(Uri uri) { final String queryUri = getContext().getString(R.string.config_non_public_slice_query_uri); if (!TextUtils.isEmpty(queryUri) && TextUtils.equals(uri.toString(), queryUri)) { // check if the calling package is eligible for private slices final int callingUid = Binder.getCallingUid(); final boolean hasPermission = getContext().checkPermission( android.Manifest.permission.READ_SEARCH_INDEXABLES, Binder.getCallingPid(), callingUid) == PackageManager.PERMISSION_GRANTED; final String callingPackage = getContext().getPackageManager() .getPackagesForUid(callingUid)[0]; return hasPermission && TextUtils.equals(callingPackage, getContext().getString(R.string.config_settingsintelligence_package_name)); } return false; } private void startBackgroundWorker(Sliceable sliceable, Uri uri) { final Class workerClass = sliceable.getBackgroundWorkerClass(); if (workerClass == null) { Loading src/com/android/settings/slices/SlicesDatabaseAccessor.java +7 −5 Original line number Diff line number Diff line Loading @@ -88,16 +88,18 @@ public class SlicesDatabaseAccessor { } /** * @return a list of Slice {@link Uri}s matching {@param authority}. * @return a list of Slice {@link Uri}s based on their visibility {@param isPublicSlice } and * {@param authority}. */ public List<Uri> getSliceUris(String authority) { public List<Uri> getSliceUris(String authority, boolean isPublicSlice) { verifyIndexing(); final List<Uri> uris = new ArrayList<>(); final String whereClause = IndexColumns.PUBLIC_SLICE + (isPublicSlice ? "=1" : "=0"); final SQLiteDatabase database = mHelper.getReadableDatabase(); final String[] columns = new String[]{IndexColumns.SLICE_URI}; try (final Cursor resultCursor = database.query(TABLE_SLICES_INDEX, columns, null /* where */, null /* selection */, null /* groupBy */, null /* having */, null /* orderBy */)) { try (Cursor resultCursor = database.query(TABLE_SLICES_INDEX, columns, whereClause /* where */, null /* selection */, null /* groupBy */, null /* having */, null /* orderBy */)) { if (!resultCursor.moveToFirst()) { return uris; } Loading tests/robotests/res/values-mcc999/config.xml +3 −0 Original line number Diff line number Diff line Loading @@ -94,4 +94,7 @@ <item>injected_tile_key</item> <item>injected_tile_key2</item> </string-array> <!-- Uri to query non-public Slice Uris. --> <string name="config_non_public_slice_query_uri" translatable="false">content://com.android.settings.slices/test</string> </resources> Loading
res/values/config.xml +3 −0 Original line number Diff line number Diff line Loading @@ -425,4 +425,7 @@ <string-array name="config_panel_keep_observe_uri" translatable="false"> <item>content://com.android.settings.slices/intent/media_output_indicator</item> </string-array> <!-- Uri to query non-public Slice Uris. --> <string name="config_non_public_slice_query_uri" translatable="false"></string> </resources>
src/com/android/settings/search/SettingsSearchIndexablesProvider.java +5 −2 Original line number Diff line number Diff line Loading @@ -61,6 +61,7 @@ import android.util.Log; import androidx.annotation.Nullable; import androidx.slice.SliceViewManager; import com.android.settings.R; import com.android.settings.SettingsActivity; import com.android.settings.dashboard.DashboardFeatureProvider; import com.android.settings.overlay.FeatureFactory; Loading Loading @@ -216,11 +217,13 @@ public class SettingsSearchIndexablesProvider extends SearchIndexablesProvider { public Cursor querySliceUriPairs() { final SliceViewManager manager = SliceViewManager.getInstance(getContext()); final MatrixCursor cursor = new MatrixCursor(SLICE_URI_PAIRS_COLUMNS); final Uri baseUri = new Uri.Builder() final String queryUri = getContext().getString(R.string.config_non_public_slice_query_uri); final Uri baseUri = !TextUtils.isEmpty(queryUri) ? Uri.parse(queryUri) : new Uri.Builder() .scheme(ContentResolver.SCHEME_CONTENT) .authority(SettingsSliceProvider.SLICE_AUTHORITY) .build(); final Uri platformBaseUri = new Uri.Builder() .scheme(ContentResolver.SCHEME_CONTENT) Loading
src/com/android/settings/slices/SettingsSliceProvider.java +39 −5 Original line number Diff line number Diff line Loading @@ -20,10 +20,13 @@ import static android.Manifest.permission.READ_SEARCH_INDEXABLES; import android.app.PendingIntent; import android.app.slice.SliceManager; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.PackageManager; import android.net.Uri; import android.os.Binder; import android.os.StrictMode; import android.provider.Settings; import android.provider.SettingsSlicesContract; Loading Loading @@ -265,16 +268,29 @@ public class SettingsSliceProvider extends SliceProvider { @Override public Collection<Uri> onGetSliceDescendants(Uri uri) { final List<Uri> descendants = new ArrayList<>(); final Pair<Boolean, String> pathData = SliceBuilderUtils.getPathData(uri); Uri finalUri = uri; if (isPrivateSlicesNeeded(finalUri)) { descendants.addAll( mSlicesDatabaseAccessor.getSliceUris(finalUri.getAuthority(), false /* isPublicSlice */)); Log.d(TAG, "provide " + descendants.size() + " non-public slices"); finalUri = new Uri.Builder() .scheme(ContentResolver.SCHEME_CONTENT) .authority(finalUri.getAuthority()) .build(); } final Pair<Boolean, String> pathData = SliceBuilderUtils.getPathData(finalUri); if (pathData != null) { // Uri has a full path and will not have any descendants. descendants.add(uri); descendants.add(finalUri); return descendants; } final String authority = uri.getAuthority(); final String path = uri.getPath(); final String authority = finalUri.getAuthority(); final String path = finalUri.getPath(); final boolean isPathEmpty = path.isEmpty(); // Path is anything but empty, "action", or "intent". Return empty list. Loading @@ -286,7 +302,7 @@ public class SettingsSliceProvider extends SliceProvider { } // Add all descendants from db with matching authority. descendants.addAll(mSlicesDatabaseAccessor.getSliceUris(authority)); descendants.addAll(mSlicesDatabaseAccessor.getSliceUris(authority, true /*isPublicSlice*/)); if (isPathEmpty && TextUtils.isEmpty(authority)) { // No path nor authority. Return all possible Uris by adding all special slice uri Loading Loading @@ -404,6 +420,24 @@ public class SettingsSliceProvider extends SliceProvider { return set; } @VisibleForTesting boolean isPrivateSlicesNeeded(Uri uri) { final String queryUri = getContext().getString(R.string.config_non_public_slice_query_uri); if (!TextUtils.isEmpty(queryUri) && TextUtils.equals(uri.toString(), queryUri)) { // check if the calling package is eligible for private slices final int callingUid = Binder.getCallingUid(); final boolean hasPermission = getContext().checkPermission( android.Manifest.permission.READ_SEARCH_INDEXABLES, Binder.getCallingPid(), callingUid) == PackageManager.PERMISSION_GRANTED; final String callingPackage = getContext().getPackageManager() .getPackagesForUid(callingUid)[0]; return hasPermission && TextUtils.equals(callingPackage, getContext().getString(R.string.config_settingsintelligence_package_name)); } return false; } private void startBackgroundWorker(Sliceable sliceable, Uri uri) { final Class workerClass = sliceable.getBackgroundWorkerClass(); if (workerClass == null) { Loading
src/com/android/settings/slices/SlicesDatabaseAccessor.java +7 −5 Original line number Diff line number Diff line Loading @@ -88,16 +88,18 @@ public class SlicesDatabaseAccessor { } /** * @return a list of Slice {@link Uri}s matching {@param authority}. * @return a list of Slice {@link Uri}s based on their visibility {@param isPublicSlice } and * {@param authority}. */ public List<Uri> getSliceUris(String authority) { public List<Uri> getSliceUris(String authority, boolean isPublicSlice) { verifyIndexing(); final List<Uri> uris = new ArrayList<>(); final String whereClause = IndexColumns.PUBLIC_SLICE + (isPublicSlice ? "=1" : "=0"); final SQLiteDatabase database = mHelper.getReadableDatabase(); final String[] columns = new String[]{IndexColumns.SLICE_URI}; try (final Cursor resultCursor = database.query(TABLE_SLICES_INDEX, columns, null /* where */, null /* selection */, null /* groupBy */, null /* having */, null /* orderBy */)) { try (Cursor resultCursor = database.query(TABLE_SLICES_INDEX, columns, whereClause /* where */, null /* selection */, null /* groupBy */, null /* having */, null /* orderBy */)) { if (!resultCursor.moveToFirst()) { return uris; } Loading
tests/robotests/res/values-mcc999/config.xml +3 −0 Original line number Diff line number Diff line Loading @@ -94,4 +94,7 @@ <item>injected_tile_key</item> <item>injected_tile_key2</item> </string-array> <!-- Uri to query non-public Slice Uris. --> <string name="config_non_public_slice_query_uri" translatable="false">content://com.android.settings.slices/test</string> </resources>