17f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monk/* 27f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monk * Copyright (C) 2018 The Android Open Source Project 37f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monk * 47f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monk * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file 57f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monk * except in compliance with the License. You may obtain a copy of the License at 67f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monk * 77f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monk * http://www.apache.org/licenses/LICENSE-2.0 87f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monk * 97f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monk * Unless required by applicable law or agreed to in writing, software distributed under the 107f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monk * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 117f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monk * KIND, either express or implied. See the License for the specific language governing 127f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monk * permissions and limitations under the License. 137f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monk */ 147f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monk 157f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monkpackage com.android.server.slice; 167f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monk 177f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monkimport android.app.slice.SliceProvider; 187f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monkimport android.content.ContentResolver; 197f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monkimport android.content.Context; 207f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monkimport android.content.pm.PackageInfo; 217f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monkimport android.net.Uri; 227f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monkimport android.os.Binder; 237f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monkimport android.os.Bundle; 247f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monkimport android.os.Process; 257f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monkimport android.os.ShellCommand; 267f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monkimport android.util.ArraySet; 277f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monk 287f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monkimport java.io.PrintWriter; 297f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monkimport java.util.List; 307f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monkimport java.util.Set; 317f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monk 327f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monkpublic class SliceShellCommand extends ShellCommand { 337f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monk 347f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monk private final SliceManagerService mService; 357f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monk 367f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monk public SliceShellCommand(SliceManagerService service) { 377f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monk mService = service; 387f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monk } 397f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monk 407f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monk @Override 417f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monk public int onCommand(String cmd) { 427f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monk if (cmd == null) { 437f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monk return handleDefaultCommands(cmd); 447f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monk } 457f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monk switch (cmd) { 467f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monk case "get-permissions": 477f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monk return runGetPermissions(getNextArgRequired()); 487f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monk } 497f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monk return 0; 507f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monk } 517f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monk 527f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monk @Override 537f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monk public void onHelp() { 547f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monk final PrintWriter pw = getOutPrintWriter(); 557f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monk pw.println("Status bar commands:"); 567f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monk pw.println(" help"); 577f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monk pw.println(" Print this help text."); 587f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monk pw.println(""); 597f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monk pw.println(" get-permissions <authority>"); 607f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monk pw.println(" List the pkgs that have permission to an authority."); 617f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monk pw.println(""); 627f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monk 637f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monk } 647f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monk 657f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monk private int runGetPermissions(String authority) { 667f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monk if (Binder.getCallingUid() != Process.SHELL_UID 677f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monk && Binder.getCallingUid() != Process.ROOT_UID) { 687f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monk getOutPrintWriter().println("Only shell can get permissions"); 697f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monk return -1; 707f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monk } 717f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monk Context context = mService.getContext(); 727f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monk long ident = Binder.clearCallingIdentity(); 737f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monk try { 747f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monk Uri uri = new Uri.Builder() 757f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monk .scheme(ContentResolver.SCHEME_CONTENT) 767f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monk .authority(authority) 777f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monk .build(); 787f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monk if (!SliceProvider.SLICE_TYPE.equals(context.getContentResolver().getType(uri))) { 797f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monk getOutPrintWriter().println(authority + " is not a slice provider"); 807f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monk return -1; 817f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monk } 827f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monk Bundle b = context.getContentResolver().call(uri, SliceProvider.METHOD_GET_PERMISSIONS, 837f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monk null, null); 847f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monk if (b == null) { 857f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monk getOutPrintWriter().println("An error occurred getting permissions"); 867f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monk return -1; 877f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monk } 887f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monk String[] permissions = b.getStringArray(SliceProvider.EXTRA_RESULT); 897f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monk final PrintWriter pw = getOutPrintWriter(); 907f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monk Set<String> listedPackages = new ArraySet<>(); 917f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monk if (permissions != null && permissions.length != 0) { 927f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monk List<PackageInfo> apps = 937f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monk context.getPackageManager().getPackagesHoldingPermissions(permissions, 0); 947f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monk for (PackageInfo app : apps) { 957f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monk pw.println(app.packageName); 967f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monk listedPackages.add(app.packageName); 977f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monk } 987f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monk } 997f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monk for (String pkg : mService.getAllPackagesGranted(authority)) { 1007f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monk if (!listedPackages.contains(pkg)) { 1017f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monk pw.println(pkg); 1027f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monk listedPackages.add(pkg); 1037f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monk } 1047f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monk } 1057f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monk } finally { 1067f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monk Binder.restoreCallingIdentity(ident); 1077f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monk } 1087f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monk return 0; 1097f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monk } 1107f01f3b6198465c70e81c5edcc1be2fa8199efd8Jason Monk} 111