Loading services/core/java/com/android/server/pm/InstantAppRegistry.java +67 −48 Original line number Diff line number Diff line Loading @@ -117,7 +117,13 @@ class InstantAppRegistry { public byte[] getInstantAppCookieLPw(@NonNull String packageName, @UserIdInt int userId) { byte[] pendingCookie = mCookiePersistence.getPendingPersistCookie(userId, packageName); // Only installed packages can get their own cookie PackageParser.Package pkg = mService.mPackages.get(packageName); if (pkg == null) { return null; } byte[] pendingCookie = mCookiePersistence.getPendingPersistCookieLPr(pkg, userId); if (pendingCookie != null) { return pendingCookie; } Loading @@ -144,14 +150,13 @@ class InstantAppRegistry { } } // Only an installed package can set its own cookie PackageParser.Package pkg = mService.mPackages.get(packageName); if (pkg == null) { return false; } File cookieFile = computeInstantCookieFile(pkg, userId); mCookiePersistence.schedulePersist(userId, packageName, cookieFile, cookie); mCookiePersistence.schedulePersistLPw(userId, pkg, cookie); return true; } Loading @@ -172,14 +177,13 @@ class InstantAppRegistry { if (cookie == null || cookie.length <= 0) { return; } } try (FileOutputStream fos = new FileOutputStream(cookieFile)) { fos.write(cookie, 0, cookie.length); } catch (IOException e) { Slog.e(LOG_TAG, "Error writing instant app cookie file: " + cookieFile, e); } } } public Bitmap getInstantAppIconLPw(@NonNull String packageName, @UserIdInt int userId) { Loading Loading @@ -242,6 +246,8 @@ class InstantAppRegistry { if (!currentCookieFile.equals(expectedCookeFile)) { Slog.i(LOG_TAG, "Signature for package " + pkg.packageName + " changed - dropping cookie"); // Make sure a pending write for the old signed app is cancelled mCookiePersistence.cancelPendingPersistLPw(pkg, userId); currentCookieFile.delete(); } } Loading Loading @@ -894,75 +900,88 @@ class InstantAppRegistry { // Handler allows removing messages by id and tag where the // tag is compared using ==. So to allow cancelling the // pending persistence for an app under a given user we use // the fact that package names are interned in the system // process so the == comparison would match and we end up // with a way to cancel persisting the cookie for a user // and package. private final SparseArray<ArrayMap<String, byte[]>> mPendingPersistCookies = new SparseArray<>(); // the fact that package are cached by the system so the == // comparison would match and we end up with a way to cancel // persisting the cookie for a user and package. private final SparseArray<ArrayMap<PackageParser.Package, SomeArgs>> mPendingPersistCookies = new SparseArray<>(); public CookiePersistence(Looper looper) { super(looper); } public void schedulePersist(@UserIdInt int userId, @NonNull String packageName, @NonNull File cookieFile, @NonNull byte[] cookie) { cancelPendingPersist(userId, packageName); addPendingPersistCookie(userId, packageName, cookie); SomeArgs args = SomeArgs.obtain(); args.arg1 = packageName; args.arg2 = cookieFile; sendMessageDelayed(obtainMessage(userId, args), public void schedulePersistLPw(@UserIdInt int userId, @NonNull PackageParser.Package pkg, @NonNull byte[] cookie) { File cookieFile = computeInstantCookieFile(pkg, userId); cancelPendingPersistLPw(pkg, userId); addPendingPersistCookieLPw(userId, pkg, cookie, cookieFile); sendMessageDelayed(obtainMessage(userId, pkg), PERSIST_COOKIE_DELAY_MILLIS); } public @Nullable byte[] getPendingPersistCookie(@UserIdInt int userId, @NonNull String packageName) { ArrayMap<String, byte[]> pendingWorkForUser = mPendingPersistCookies.get(userId); public @Nullable byte[] getPendingPersistCookieLPr(@NonNull PackageParser.Package pkg, @UserIdInt int userId) { ArrayMap<PackageParser.Package, SomeArgs> pendingWorkForUser = mPendingPersistCookies.get(userId); if (pendingWorkForUser != null) { return pendingWorkForUser.remove(packageName); SomeArgs state = pendingWorkForUser.get(pkg); if (state != null) { return (byte[]) state.arg1; } } return null; } private void cancelPendingPersist(@UserIdInt int userId, @NonNull String packageName) { removePendingPersistCookie(userId, packageName); removeMessages(userId, packageName); public void cancelPendingPersistLPw(@NonNull PackageParser.Package pkg, @UserIdInt int userId) { removeMessages(userId, pkg); SomeArgs state = removePendingPersistCookieLPr(pkg, userId); if (state != null) { state.recycle(); } } private void addPendingPersistCookie(@UserIdInt int userId, @NonNull String packageName, @NonNull byte[] cookie) { ArrayMap<String, byte[]> pendingWorkForUser = mPendingPersistCookies.get(userId); private void addPendingPersistCookieLPw(@UserIdInt int userId, @NonNull PackageParser.Package pkg, @NonNull byte[] cookie, @NonNull File cookieFile) { ArrayMap<PackageParser.Package, SomeArgs> pendingWorkForUser = mPendingPersistCookies.get(userId); if (pendingWorkForUser == null) { pendingWorkForUser = new ArrayMap<>(); mPendingPersistCookies.put(userId, pendingWorkForUser); } pendingWorkForUser.put(packageName, cookie); SomeArgs args = SomeArgs.obtain(); args.arg1 = cookie; args.arg2 = cookieFile; pendingWorkForUser.put(pkg, args); } private byte[] removePendingPersistCookie(@UserIdInt int userId, @NonNull String packageName) { ArrayMap<String, byte[]> pendingWorkForUser = mPendingPersistCookies.get(userId); byte[] cookie = null; private SomeArgs removePendingPersistCookieLPr(@NonNull PackageParser.Package pkg, @UserIdInt int userId) { ArrayMap<PackageParser.Package, SomeArgs> pendingWorkForUser = mPendingPersistCookies.get(userId); SomeArgs state = null; if (pendingWorkForUser != null) { cookie = pendingWorkForUser.remove(packageName); state = pendingWorkForUser.remove(pkg); if (pendingWorkForUser.isEmpty()) { mPendingPersistCookies.remove(userId); } } return cookie; return state; } @Override public void handleMessage(Message message) { int userId = message.what; SomeArgs args = (SomeArgs) message.obj; String packageName = (String) args.arg1; File cookieFile = (File) args.arg2; args.recycle(); byte[] cookie = removePendingPersistCookie(userId, packageName); persistInstantApplicationCookie(cookie, packageName, cookieFile, userId); PackageParser.Package pkg = (PackageParser.Package) message.obj; SomeArgs state = removePendingPersistCookieLPr(pkg, userId); if (state == null) { return; } byte[] cookie = (byte[]) state.arg1; File cookieFile = (File) state.arg2; state.recycle(); persistInstantApplicationCookie(cookie, pkg.packageName, cookieFile, userId); } } } Loading
services/core/java/com/android/server/pm/InstantAppRegistry.java +67 −48 Original line number Diff line number Diff line Loading @@ -117,7 +117,13 @@ class InstantAppRegistry { public byte[] getInstantAppCookieLPw(@NonNull String packageName, @UserIdInt int userId) { byte[] pendingCookie = mCookiePersistence.getPendingPersistCookie(userId, packageName); // Only installed packages can get their own cookie PackageParser.Package pkg = mService.mPackages.get(packageName); if (pkg == null) { return null; } byte[] pendingCookie = mCookiePersistence.getPendingPersistCookieLPr(pkg, userId); if (pendingCookie != null) { return pendingCookie; } Loading @@ -144,14 +150,13 @@ class InstantAppRegistry { } } // Only an installed package can set its own cookie PackageParser.Package pkg = mService.mPackages.get(packageName); if (pkg == null) { return false; } File cookieFile = computeInstantCookieFile(pkg, userId); mCookiePersistence.schedulePersist(userId, packageName, cookieFile, cookie); mCookiePersistence.schedulePersistLPw(userId, pkg, cookie); return true; } Loading @@ -172,14 +177,13 @@ class InstantAppRegistry { if (cookie == null || cookie.length <= 0) { return; } } try (FileOutputStream fos = new FileOutputStream(cookieFile)) { fos.write(cookie, 0, cookie.length); } catch (IOException e) { Slog.e(LOG_TAG, "Error writing instant app cookie file: " + cookieFile, e); } } } public Bitmap getInstantAppIconLPw(@NonNull String packageName, @UserIdInt int userId) { Loading Loading @@ -242,6 +246,8 @@ class InstantAppRegistry { if (!currentCookieFile.equals(expectedCookeFile)) { Slog.i(LOG_TAG, "Signature for package " + pkg.packageName + " changed - dropping cookie"); // Make sure a pending write for the old signed app is cancelled mCookiePersistence.cancelPendingPersistLPw(pkg, userId); currentCookieFile.delete(); } } Loading Loading @@ -894,75 +900,88 @@ class InstantAppRegistry { // Handler allows removing messages by id and tag where the // tag is compared using ==. So to allow cancelling the // pending persistence for an app under a given user we use // the fact that package names are interned in the system // process so the == comparison would match and we end up // with a way to cancel persisting the cookie for a user // and package. private final SparseArray<ArrayMap<String, byte[]>> mPendingPersistCookies = new SparseArray<>(); // the fact that package are cached by the system so the == // comparison would match and we end up with a way to cancel // persisting the cookie for a user and package. private final SparseArray<ArrayMap<PackageParser.Package, SomeArgs>> mPendingPersistCookies = new SparseArray<>(); public CookiePersistence(Looper looper) { super(looper); } public void schedulePersist(@UserIdInt int userId, @NonNull String packageName, @NonNull File cookieFile, @NonNull byte[] cookie) { cancelPendingPersist(userId, packageName); addPendingPersistCookie(userId, packageName, cookie); SomeArgs args = SomeArgs.obtain(); args.arg1 = packageName; args.arg2 = cookieFile; sendMessageDelayed(obtainMessage(userId, args), public void schedulePersistLPw(@UserIdInt int userId, @NonNull PackageParser.Package pkg, @NonNull byte[] cookie) { File cookieFile = computeInstantCookieFile(pkg, userId); cancelPendingPersistLPw(pkg, userId); addPendingPersistCookieLPw(userId, pkg, cookie, cookieFile); sendMessageDelayed(obtainMessage(userId, pkg), PERSIST_COOKIE_DELAY_MILLIS); } public @Nullable byte[] getPendingPersistCookie(@UserIdInt int userId, @NonNull String packageName) { ArrayMap<String, byte[]> pendingWorkForUser = mPendingPersistCookies.get(userId); public @Nullable byte[] getPendingPersistCookieLPr(@NonNull PackageParser.Package pkg, @UserIdInt int userId) { ArrayMap<PackageParser.Package, SomeArgs> pendingWorkForUser = mPendingPersistCookies.get(userId); if (pendingWorkForUser != null) { return pendingWorkForUser.remove(packageName); SomeArgs state = pendingWorkForUser.get(pkg); if (state != null) { return (byte[]) state.arg1; } } return null; } private void cancelPendingPersist(@UserIdInt int userId, @NonNull String packageName) { removePendingPersistCookie(userId, packageName); removeMessages(userId, packageName); public void cancelPendingPersistLPw(@NonNull PackageParser.Package pkg, @UserIdInt int userId) { removeMessages(userId, pkg); SomeArgs state = removePendingPersistCookieLPr(pkg, userId); if (state != null) { state.recycle(); } } private void addPendingPersistCookie(@UserIdInt int userId, @NonNull String packageName, @NonNull byte[] cookie) { ArrayMap<String, byte[]> pendingWorkForUser = mPendingPersistCookies.get(userId); private void addPendingPersistCookieLPw(@UserIdInt int userId, @NonNull PackageParser.Package pkg, @NonNull byte[] cookie, @NonNull File cookieFile) { ArrayMap<PackageParser.Package, SomeArgs> pendingWorkForUser = mPendingPersistCookies.get(userId); if (pendingWorkForUser == null) { pendingWorkForUser = new ArrayMap<>(); mPendingPersistCookies.put(userId, pendingWorkForUser); } pendingWorkForUser.put(packageName, cookie); SomeArgs args = SomeArgs.obtain(); args.arg1 = cookie; args.arg2 = cookieFile; pendingWorkForUser.put(pkg, args); } private byte[] removePendingPersistCookie(@UserIdInt int userId, @NonNull String packageName) { ArrayMap<String, byte[]> pendingWorkForUser = mPendingPersistCookies.get(userId); byte[] cookie = null; private SomeArgs removePendingPersistCookieLPr(@NonNull PackageParser.Package pkg, @UserIdInt int userId) { ArrayMap<PackageParser.Package, SomeArgs> pendingWorkForUser = mPendingPersistCookies.get(userId); SomeArgs state = null; if (pendingWorkForUser != null) { cookie = pendingWorkForUser.remove(packageName); state = pendingWorkForUser.remove(pkg); if (pendingWorkForUser.isEmpty()) { mPendingPersistCookies.remove(userId); } } return cookie; return state; } @Override public void handleMessage(Message message) { int userId = message.what; SomeArgs args = (SomeArgs) message.obj; String packageName = (String) args.arg1; File cookieFile = (File) args.arg2; args.recycle(); byte[] cookie = removePendingPersistCookie(userId, packageName); persistInstantApplicationCookie(cookie, packageName, cookieFile, userId); PackageParser.Package pkg = (PackageParser.Package) message.obj; SomeArgs state = removePendingPersistCookieLPr(pkg, userId); if (state == null) { return; } byte[] cookie = (byte[]) state.arg1; File cookieFile = (File) state.arg2; state.recycle(); persistInstantApplicationCookie(cookie, pkg.packageName, cookieFile, userId); } } }