private String getDocIdForFile(File file) throws FileNotFoundException { String path = file.getAbsolutePath(); // Find the most-specific root path String mostSpecificId = null; String mostSpecificPath = null; synchronized (mRootsLock) { for (int i = 0; i < mRoots.size(); i++) { final String rootId = mRoots.keyAt(i); final String rootPath = mRoots.valueAt(i).path.getAbsolutePath(); if (path.startsWith(rootPath) && (mostSpecificPath == null || rootPath.length() > mostSpecificPath.length())) { mostSpecificId = rootId; mostSpecificPath = rootPath; } } } if (mostSpecificPath == null) { throw new FileNotFoundException("Failed to find root that contains " + path); } // Start at first char of path under root final String rootPath = mostSpecificPath; if (rootPath.equals(path)) { path = ""; } else if (rootPath.endsWith("/")) { path = path.substring(rootPath.length()); } else { path = path.substring(rootPath.length() + 1); } return mostSpecificId + ':' + path; }
public UsbPort[] getPorts() { synchronized (mLock) { final int count = mPorts.size(); final UsbPort[] result = new UsbPort[count]; for (int i = 0; i < count; i++) { result[i] = mPorts.valueAt(i).mUsbPort; } return result; } }
public boolean getAppsWithPermissionsCount(Context context, int[] counts) { ArraySet<String> launcherPkgs = Utils.getLauncherPackages(context); // Indexed by uid. ArrayMap<String, Boolean> grantedApps = new ArrayMap<>(); ArrayMap<String, Boolean> allApps = new ArrayMap<>(); for (String group : Utils.MODERN_PERMISSION_GROUPS) { PermissionApps permissionApps = new PermissionApps(context, group, null); permissionApps.loadNowWithoutUi(); for (PermissionApp app : permissionApps.getApps()) { String key = app.getKey(); if (Utils.isSystem(app, launcherPkgs)) { // We default to not showing system apps, so hide them from count. continue; } if (app.areRuntimePermissionsGranted()) { grantedApps.put(key, true); } allApps.put(key, true); } } counts[0] = grantedApps.size(); counts[1] = allApps.size(); return true; }
@Override public void dump(FileDescriptor fd, PrintWriter writer, String[] args) { final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " ", 160); synchronized (mRootsLock) { for (int i = 0; i < mRoots.size(); i++) { final RootInfo root = mRoots.valueAt(i); pw.println("Root{" + root.rootId + "}:"); pw.increaseIndent(); pw.printPair("flags", DebugUtils.flagsToString(Root.class, "FLAG_", root.flags)); pw.println(); pw.printPair("title", root.title); pw.printPair("docId", root.docId); pw.println(); pw.printPair("path", root.path); pw.printPair("visiblePath", root.visiblePath); pw.decreaseIndent(); pw.println(); } } }
private void updatePortsLocked(IndentingPrintWriter pw) { // Assume all ports are gone unless informed otherwise. // Kind of pessimistic but simple. for (int i = mPorts.size(); i-- > 0; ) { mPorts.valueAt(i).mDisposition = PortInfo.DISPOSITION_REMOVED; } // Enumerate all extant ports. if (!mSimulatedPorts.isEmpty()) { final int count = mSimulatedPorts.size(); for (int i = 0; i < count; i++) { final SimulatedPortInfo portInfo = mSimulatedPorts.valueAt(i); addOrUpdatePortLocked( portInfo.mPortId, portInfo.mSupportedModes, portInfo.mCurrentMode, portInfo.mCanChangeMode, portInfo.mCurrentPowerRole, portInfo.mCanChangePowerRole, portInfo.mCurrentDataRole, portInfo.mCanChangeDataRole, pw); } } else if (mHaveKernelSupport) { final File[] portDirs = new File(SYSFS_CLASS).listFiles(); if (portDirs != null) { for (File portDir : portDirs) { if (!portDir.isDirectory()) { continue; } // Parse the sysfs file contents. final String portId = portDir.getName(); final int supportedModes = readSupportedModes(portDir); final int currentMode = readCurrentMode(portDir); final boolean canChangeMode = canChangeMode(portDir); final int currentPowerRole = readCurrentPowerRole(portDir); final boolean canChangePowerRole = canChangePowerRole(portDir); final int currentDataRole = readCurrentDataRole(portDir); final boolean canChangeDataRole = canChangeDataRole(portDir); addOrUpdatePortLocked( portId, supportedModes, currentMode, canChangeMode, currentPowerRole, canChangePowerRole, currentDataRole, canChangeDataRole, pw); } } } // Process the updates. // Once finished, the list of ports will only contain ports in DISPOSITION_READY. for (int i = mPorts.size(); i-- > 0; ) { final PortInfo portInfo = mPorts.valueAt(i); switch (portInfo.mDisposition) { case PortInfo.DISPOSITION_ADDED: handlePortAddedLocked(portInfo, pw); portInfo.mDisposition = PortInfo.DISPOSITION_READY; break; case PortInfo.DISPOSITION_CHANGED: handlePortChangedLocked(portInfo, pw); portInfo.mDisposition = PortInfo.DISPOSITION_READY; break; case PortInfo.DISPOSITION_REMOVED: mPorts.removeAt(i); portInfo.mUsbPortStatus = null; // must do this early handlePortRemovedLocked(portInfo, pw); break; } } }
boolean dumpMap( PrintWriter out, String titlePrefix, String title, String prefix, ArrayMap<String, F[]> map, String packageName, boolean printFilter, boolean collapseDuplicates) { final String eprefix = prefix + " "; final String fprefix = prefix + " "; final ArrayMap<Object, MutableInt> found = new ArrayMap<>(); boolean printedSomething = false; Printer printer = null; for (int mapi = 0; mapi < map.size(); mapi++) { F[] a = map.valueAt(mapi); final int N = a.length; boolean printedHeader = false; F filter; if (collapseDuplicates && !printFilter) { found.clear(); for (int i = 0; i < N && (filter = a[i]) != null; i++) { if (packageName != null && !isPackageForFilter(packageName, filter)) { continue; } Object label = filterToLabel(filter); int index = found.indexOfKey(label); if (index < 0) { found.put(label, new MutableInt(1)); } else { found.valueAt(index).value++; } } for (int i = 0; i < found.size(); i++) { if (title != null) { out.print(titlePrefix); out.println(title); title = null; } if (!printedHeader) { out.print(eprefix); out.print(map.keyAt(mapi)); out.println(":"); printedHeader = true; } printedSomething = true; dumpFilterLabel(out, fprefix, found.keyAt(i), found.valueAt(i).value); } } else { for (int i = 0; i < N && (filter = a[i]) != null; i++) { if (packageName != null && !isPackageForFilter(packageName, filter)) { continue; } if (title != null) { out.print(titlePrefix); out.println(title); title = null; } if (!printedHeader) { out.print(eprefix); out.print(map.keyAt(mapi)); out.println(":"); printedHeader = true; } printedSomething = true; dumpFilter(out, fprefix, filter); if (printFilter) { if (printer == null) { printer = new PrintWriterPrinter(out); } filter.dump(printer, fprefix + " "); } } } } return printedSomething; }
private void handleReadPrintJobsLocked() { // Make a map with the files for a print job since we may have // to delete some. One example of getting orphan files if the // spooler crashes while constructing a print job. We do not // persist partially populated print jobs under construction to // avoid special handling for various attributes missing. ArrayMap<PrintJobId, File> fileForJobMap = null; File[] files = getFilesDir().listFiles(); if (files != null) { final int fileCount = files.length; for (int i = 0; i < fileCount; i++) { File file = files[i]; if (file.isFile() && file.getName().startsWith(PRINT_JOB_FILE_PREFIX)) { if (fileForJobMap == null) { fileForJobMap = new ArrayMap<PrintJobId, File>(); } String printJobIdString = file.getName().substring(PRINT_JOB_FILE_PREFIX.length(), file.getName().indexOf('.')); PrintJobId printJobId = PrintJobId.unflattenFromString(printJobIdString); fileForJobMap.put(printJobId, file); } } } final int printJobCount = mPrintJobs.size(); for (int i = 0; i < printJobCount; i++) { PrintJobInfo printJob = mPrintJobs.get(i); // We want to have only the orphan files at the end. if (fileForJobMap != null) { fileForJobMap.remove(printJob.getId()); } switch (printJob.getState()) { case PrintJobInfo.STATE_QUEUED: case PrintJobInfo.STATE_STARTED: case PrintJobInfo.STATE_BLOCKED: { // We have a print job that was queued or started or blocked in // the past but the device battery died or a crash occurred. In // this case we assume the print job failed and let the user // decide whether to restart the job or just cancel it. setPrintJobState( printJob.getId(), PrintJobInfo.STATE_FAILED, getString(R.string.no_connection_to_printer)); } break; } } if (!mPrintJobs.isEmpty()) { // Update the notification. mNotificationController.onUpdateNotifications(mPrintJobs); } // Delete the orphan files. if (fileForJobMap != null) { final int orphanFileCount = fileForJobMap.size(); for (int i = 0; i < orphanFileCount; i++) { File file = fileForJobMap.valueAt(i); file.delete(); } } }
private void updateVolumesLocked() { mRoots.clear(); final int userId = UserHandle.myUserId(); final List<VolumeInfo> volumes = mStorageManager.getVolumes(); for (VolumeInfo volume : volumes) { if (!volume.isMountedReadable()) continue; final String rootId; final String title; if (volume.getType() == VolumeInfo.TYPE_EMULATED) { // We currently only support a single emulated volume mounted at // a time, and it's always considered the primary rootId = ROOT_ID_PRIMARY_EMULATED; if (VolumeInfo.ID_EMULATED_INTERNAL.equals(volume.getId())) { title = getContext().getString(R.string.root_internal_storage); } else { final VolumeInfo privateVol = mStorageManager.findPrivateForEmulated(volume); title = mStorageManager.getBestVolumeDescription(privateVol); } } else if (volume.getType() == VolumeInfo.TYPE_PUBLIC) { rootId = volume.getFsUuid(); title = mStorageManager.getBestVolumeDescription(volume); } else { // Unsupported volume; ignore continue; } if (TextUtils.isEmpty(rootId)) { Log.d(TAG, "Missing UUID for " + volume.getId() + "; skipping"); continue; } if (mRoots.containsKey(rootId)) { Log.w(TAG, "Duplicate UUID " + rootId + " for " + volume.getId() + "; skipping"); continue; } try { final RootInfo root = new RootInfo(); mRoots.put(rootId, root); root.rootId = rootId; root.flags = Root.FLAG_SUPPORTS_CREATE | Root.FLAG_LOCAL_ONLY | Root.FLAG_ADVANCED | Root.FLAG_SUPPORTS_SEARCH | Root.FLAG_SUPPORTS_IS_CHILD; root.title = title; if (volume.getType() == VolumeInfo.TYPE_PUBLIC) { root.flags |= Root.FLAG_HAS_SETTINGS; } if (volume.isVisibleForRead(userId)) { root.visiblePath = volume.getPathForUser(userId); } else { root.visiblePath = null; } root.path = volume.getInternalPathForUser(userId); root.docId = getDocIdForFile(root.path); } catch (FileNotFoundException e) { throw new IllegalStateException(e); } } Log.d(TAG, "After updating volumes, found " + mRoots.size() + " active roots"); // Note this affects content://com.android.externalstorage.documents/root/39BD-07C5 // as well as content://com.android.externalstorage.documents/document/*/children, // so just notify on content://com.android.externalstorage.documents/. getContext().getContentResolver().notifyChange(BASE_URI, null, false); }