Loading core/java/android/service/contentcapture/ContentCaptureService.java +17 −11 Original line number Diff line number Diff line Loading @@ -34,6 +34,7 @@ import android.os.Looper; import android.os.RemoteException; import android.service.autofill.AutofillService; import android.util.ArrayMap; import android.util.ArraySet; import android.util.Log; import android.util.Slog; import android.view.contentcapture.ContentCaptureContext; Loading Loading @@ -171,16 +172,11 @@ public abstract class ContentCaptureService extends Service { @Deprecated public final void setContentCaptureWhitelist(@Nullable List<String> packages, @Nullable List<ComponentName> activities) { final IContentCaptureServiceCallback callback = mCallback; if (callback == null) { Log.w(TAG, "setContentCaptureWhitelist(): no server callback"); return; } try { callback.setContentCaptureWhitelist(packages, activities); } catch (RemoteException e) { e.rethrowFromSystemServer(); setContentCaptureWhitelist(toSet(packages), toSet(activities)); } private <T> ArraySet<T> toSet(@Nullable List<T> set) { return set == null ? null : new ArraySet<T>(set); } /** Loading @@ -197,7 +193,17 @@ public abstract class ContentCaptureService extends Service { */ public final void setContentCaptureWhitelist(@Nullable Set<String> packages, @Nullable Set<ComponentName> activities) { setContentCaptureWhitelist(toList(packages), toList(activities)); final IContentCaptureServiceCallback callback = mCallback; if (callback == null) { Log.w(TAG, "setContentCaptureWhitelist(): no server callback"); return; } try { callback.setContentCaptureWhitelist(toList(packages), toList(activities)); } catch (RemoteException e) { e.rethrowFromSystemServer(); } } private <T> ArrayList<T> toList(@Nullable Set<T> set) { Loading core/java/android/view/contentcapture/ContentCaptureSession.java +7 −0 Original line number Diff line number Diff line Loading @@ -120,6 +120,13 @@ public abstract class ContentCaptureSession implements AutoCloseable { */ public static final int STATE_INTERNAL_ERROR = 0x100; /** * Session is disabled because service didn't whitelist package. * * @hide */ public static final int STATE_PACKAGE_NOT_WHITELISTED = 0x200; private static final int INITIAL_CHILDREN_CAPACITY = 5; /** @hide */ Loading services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java +57 −8 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ import static android.view.contentcapture.ContentCaptureSession.STATE_DISABLED; import static android.view.contentcapture.ContentCaptureSession.STATE_DUPLICATED_ID; import static android.view.contentcapture.ContentCaptureSession.STATE_INTERNAL_ERROR; import static android.view.contentcapture.ContentCaptureSession.STATE_NO_SERVICE; import static android.view.contentcapture.ContentCaptureSession.STATE_PACKAGE_NOT_WHITELISTED; import static com.android.server.wm.ActivityTaskManagerInternal.ASSIST_KEY_CONTENT; import static com.android.server.wm.ActivityTaskManagerInternal.ASSIST_KEY_DATA; Loading @@ -47,7 +48,7 @@ import android.service.contentcapture.ContentCaptureService; import android.service.contentcapture.IContentCaptureServiceCallback; import android.service.contentcapture.SnapshotData; import android.util.ArrayMap; import android.util.Log; import android.util.ArraySet; import android.util.Slog; import android.view.contentcapture.UserDataRemovalRequest; Loading Loading @@ -87,6 +88,12 @@ final class ContentCapturePerUserService private final ContentCaptureServiceRemoteCallback mRemoteServiceCallback = new ContentCaptureServiceRemoteCallback(); /** * List of packages that are whitelisted to be content captured. */ @GuardedBy("mLock") private final ArraySet<String> mWhitelistedPackages = new ArraySet<>(); // TODO(b/111276913): add mechanism to prune stale sessions, similar to Autofill's ContentCapturePerUserService(@NonNull ContentCaptureManagerService master, Loading Loading @@ -185,6 +192,7 @@ final class ContentCapturePerUserService final int taskId = activityPresentationInfo.taskId; final int displayId = activityPresentationInfo.displayId; final ComponentName componentName = activityPresentationInfo.componentName; final boolean whitelisted = isWhitelistedLocked(componentName); final ComponentName serviceComponentName = getServiceComponentName(); final boolean enabled = isEnabledLocked(); if (mMaster.mRequestsHistory != null) { Loading @@ -193,7 +201,8 @@ final class ContentCapturePerUserService + " a=" + ComponentName.flattenToShortString(componentName) + " t=" + taskId + " d=" + displayId + " s=" + ComponentName.flattenToShortString(serviceComponentName) + " u=" + mUserId + " f=" + flags + (enabled ? "" : " (disabled)"); + " u=" + mUserId + " f=" + flags + (enabled ? "" : " (disabled)") + " w=" + whitelisted; mMaster.mRequestsHistory.log(historyItem); } Loading @@ -214,6 +223,16 @@ final class ContentCapturePerUserService return; } if (!whitelisted) { if (mMaster.debug) { Slog.d(TAG, "startSession(" + componentName + "): not whitelisted"); } // TODO(b/122595322): need to return STATE_ACTIVITY_NOT_WHITELISTED as well setClientState(clientReceiver, STATE_DISABLED | STATE_PACKAGE_NOT_WHITELISTED, /* binder= */ null); return; } final ContentCaptureServerSession existingSession = mSessions.get(sessionId); if (existingSession != null) { Slog.w(TAG, "startSession(id=" + existingSession + ", token=" + activityToken Loading Loading @@ -247,6 +266,26 @@ final class ContentCapturePerUserService newSession.notifySessionStartedLocked(clientReceiver); } @GuardedBy("mLock") private boolean isWhitelistedLocked(@NonNull ComponentName componentName) { // TODO(b/122595322): need to check whitelisted activities as well. final String packageName = componentName.getPackageName(); return mWhitelistedPackages.contains(packageName); } private void whitelistPackages(@NonNull List<String> packages) { // TODO(b/122595322): add CTS test for when it's null synchronized (mLock) { if (packages == null) { if (mMaster.verbose) Slog.v(TAG, "clearing all whitelisted packages"); mWhitelistedPackages.clear(); } else { if (mMaster.verbose) Slog.v(TAG, "whitelisting packages: " + packages); mWhitelistedPackages.addAll(packages); } } } // TODO(b/119613670): log metrics @GuardedBy("mLock") public void finishSessionLocked(@NonNull String sessionId) { Loading Loading @@ -378,15 +417,23 @@ final class ContentCapturePerUserService mRemoteService.dump(prefix2, pw); } final int whitelistSize = mWhitelistedPackages.size(); pw.print(prefix); pw.print("Whitelisted packages: "); pw.println(whitelistSize); for (int i = 0; i < whitelistSize; i++) { final String whitelistedPkg = mWhitelistedPackages.valueAt(i); pw.print(prefix2); pw.print(i + 1); pw.print(": "); pw.println(whitelistedPkg); } if (mSessions.isEmpty()) { pw.print(prefix); pw.println("no sessions"); } else { final int size = mSessions.size(); pw.print(prefix); pw.print("number sessions: "); pw.println(size); for (int i = 0; i < size; i++) { pw.print(prefix); pw.print("session@"); pw.println(i); final int sessionsSize = mSessions.size(); pw.print(prefix); pw.print("number sessions: "); pw.println(sessionsSize); for (int i = 0; i < sessionsSize; i++) { pw.print(prefix); pw.print("#"); pw.println(i); final ContentCaptureServerSession session = mSessions.valueAt(i); session.dumpLocked(prefix2, pw); pw.println(); } } } Loading @@ -412,10 +459,12 @@ final class ContentCapturePerUserService public void setContentCaptureWhitelist(List<String> packages, List<ComponentName> activities) { if (mMaster.verbose) { Log.v(TAG, "setContentCaptureWhitelist(packages=" + packages + ", activities=" Slog.v(TAG, "setContentCaptureWhitelist(packages=" + packages + ", activities=" + activities + ")"); } // TODO(b/122595322): implement whitelistPackages(packages); // TODO(b/122595322): whitelist activities as well // TODO(b/119613670): log metrics } } Loading Loading
core/java/android/service/contentcapture/ContentCaptureService.java +17 −11 Original line number Diff line number Diff line Loading @@ -34,6 +34,7 @@ import android.os.Looper; import android.os.RemoteException; import android.service.autofill.AutofillService; import android.util.ArrayMap; import android.util.ArraySet; import android.util.Log; import android.util.Slog; import android.view.contentcapture.ContentCaptureContext; Loading Loading @@ -171,16 +172,11 @@ public abstract class ContentCaptureService extends Service { @Deprecated public final void setContentCaptureWhitelist(@Nullable List<String> packages, @Nullable List<ComponentName> activities) { final IContentCaptureServiceCallback callback = mCallback; if (callback == null) { Log.w(TAG, "setContentCaptureWhitelist(): no server callback"); return; } try { callback.setContentCaptureWhitelist(packages, activities); } catch (RemoteException e) { e.rethrowFromSystemServer(); setContentCaptureWhitelist(toSet(packages), toSet(activities)); } private <T> ArraySet<T> toSet(@Nullable List<T> set) { return set == null ? null : new ArraySet<T>(set); } /** Loading @@ -197,7 +193,17 @@ public abstract class ContentCaptureService extends Service { */ public final void setContentCaptureWhitelist(@Nullable Set<String> packages, @Nullable Set<ComponentName> activities) { setContentCaptureWhitelist(toList(packages), toList(activities)); final IContentCaptureServiceCallback callback = mCallback; if (callback == null) { Log.w(TAG, "setContentCaptureWhitelist(): no server callback"); return; } try { callback.setContentCaptureWhitelist(toList(packages), toList(activities)); } catch (RemoteException e) { e.rethrowFromSystemServer(); } } private <T> ArrayList<T> toList(@Nullable Set<T> set) { Loading
core/java/android/view/contentcapture/ContentCaptureSession.java +7 −0 Original line number Diff line number Diff line Loading @@ -120,6 +120,13 @@ public abstract class ContentCaptureSession implements AutoCloseable { */ public static final int STATE_INTERNAL_ERROR = 0x100; /** * Session is disabled because service didn't whitelist package. * * @hide */ public static final int STATE_PACKAGE_NOT_WHITELISTED = 0x200; private static final int INITIAL_CHILDREN_CAPACITY = 5; /** @hide */ Loading
services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java +57 −8 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ import static android.view.contentcapture.ContentCaptureSession.STATE_DISABLED; import static android.view.contentcapture.ContentCaptureSession.STATE_DUPLICATED_ID; import static android.view.contentcapture.ContentCaptureSession.STATE_INTERNAL_ERROR; import static android.view.contentcapture.ContentCaptureSession.STATE_NO_SERVICE; import static android.view.contentcapture.ContentCaptureSession.STATE_PACKAGE_NOT_WHITELISTED; import static com.android.server.wm.ActivityTaskManagerInternal.ASSIST_KEY_CONTENT; import static com.android.server.wm.ActivityTaskManagerInternal.ASSIST_KEY_DATA; Loading @@ -47,7 +48,7 @@ import android.service.contentcapture.ContentCaptureService; import android.service.contentcapture.IContentCaptureServiceCallback; import android.service.contentcapture.SnapshotData; import android.util.ArrayMap; import android.util.Log; import android.util.ArraySet; import android.util.Slog; import android.view.contentcapture.UserDataRemovalRequest; Loading Loading @@ -87,6 +88,12 @@ final class ContentCapturePerUserService private final ContentCaptureServiceRemoteCallback mRemoteServiceCallback = new ContentCaptureServiceRemoteCallback(); /** * List of packages that are whitelisted to be content captured. */ @GuardedBy("mLock") private final ArraySet<String> mWhitelistedPackages = new ArraySet<>(); // TODO(b/111276913): add mechanism to prune stale sessions, similar to Autofill's ContentCapturePerUserService(@NonNull ContentCaptureManagerService master, Loading Loading @@ -185,6 +192,7 @@ final class ContentCapturePerUserService final int taskId = activityPresentationInfo.taskId; final int displayId = activityPresentationInfo.displayId; final ComponentName componentName = activityPresentationInfo.componentName; final boolean whitelisted = isWhitelistedLocked(componentName); final ComponentName serviceComponentName = getServiceComponentName(); final boolean enabled = isEnabledLocked(); if (mMaster.mRequestsHistory != null) { Loading @@ -193,7 +201,8 @@ final class ContentCapturePerUserService + " a=" + ComponentName.flattenToShortString(componentName) + " t=" + taskId + " d=" + displayId + " s=" + ComponentName.flattenToShortString(serviceComponentName) + " u=" + mUserId + " f=" + flags + (enabled ? "" : " (disabled)"); + " u=" + mUserId + " f=" + flags + (enabled ? "" : " (disabled)") + " w=" + whitelisted; mMaster.mRequestsHistory.log(historyItem); } Loading @@ -214,6 +223,16 @@ final class ContentCapturePerUserService return; } if (!whitelisted) { if (mMaster.debug) { Slog.d(TAG, "startSession(" + componentName + "): not whitelisted"); } // TODO(b/122595322): need to return STATE_ACTIVITY_NOT_WHITELISTED as well setClientState(clientReceiver, STATE_DISABLED | STATE_PACKAGE_NOT_WHITELISTED, /* binder= */ null); return; } final ContentCaptureServerSession existingSession = mSessions.get(sessionId); if (existingSession != null) { Slog.w(TAG, "startSession(id=" + existingSession + ", token=" + activityToken Loading Loading @@ -247,6 +266,26 @@ final class ContentCapturePerUserService newSession.notifySessionStartedLocked(clientReceiver); } @GuardedBy("mLock") private boolean isWhitelistedLocked(@NonNull ComponentName componentName) { // TODO(b/122595322): need to check whitelisted activities as well. final String packageName = componentName.getPackageName(); return mWhitelistedPackages.contains(packageName); } private void whitelistPackages(@NonNull List<String> packages) { // TODO(b/122595322): add CTS test for when it's null synchronized (mLock) { if (packages == null) { if (mMaster.verbose) Slog.v(TAG, "clearing all whitelisted packages"); mWhitelistedPackages.clear(); } else { if (mMaster.verbose) Slog.v(TAG, "whitelisting packages: " + packages); mWhitelistedPackages.addAll(packages); } } } // TODO(b/119613670): log metrics @GuardedBy("mLock") public void finishSessionLocked(@NonNull String sessionId) { Loading Loading @@ -378,15 +417,23 @@ final class ContentCapturePerUserService mRemoteService.dump(prefix2, pw); } final int whitelistSize = mWhitelistedPackages.size(); pw.print(prefix); pw.print("Whitelisted packages: "); pw.println(whitelistSize); for (int i = 0; i < whitelistSize; i++) { final String whitelistedPkg = mWhitelistedPackages.valueAt(i); pw.print(prefix2); pw.print(i + 1); pw.print(": "); pw.println(whitelistedPkg); } if (mSessions.isEmpty()) { pw.print(prefix); pw.println("no sessions"); } else { final int size = mSessions.size(); pw.print(prefix); pw.print("number sessions: "); pw.println(size); for (int i = 0; i < size; i++) { pw.print(prefix); pw.print("session@"); pw.println(i); final int sessionsSize = mSessions.size(); pw.print(prefix); pw.print("number sessions: "); pw.println(sessionsSize); for (int i = 0; i < sessionsSize; i++) { pw.print(prefix); pw.print("#"); pw.println(i); final ContentCaptureServerSession session = mSessions.valueAt(i); session.dumpLocked(prefix2, pw); pw.println(); } } } Loading @@ -412,10 +459,12 @@ final class ContentCapturePerUserService public void setContentCaptureWhitelist(List<String> packages, List<ComponentName> activities) { if (mMaster.verbose) { Log.v(TAG, "setContentCaptureWhitelist(packages=" + packages + ", activities=" Slog.v(TAG, "setContentCaptureWhitelist(packages=" + packages + ", activities=" + activities + ")"); } // TODO(b/122595322): implement whitelistPackages(packages); // TODO(b/122595322): whitelist activities as well // TODO(b/119613670): log metrics } } Loading