Loading services/appprediction/java/com/android/server/appprediction/AppPredictionPerUserService.java +61 −42 Original line number Diff line number Diff line Loading @@ -28,7 +28,7 @@ import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.ParceledListSlice; import android.content.pm.ServiceInfo; import android.os.IBinder; import android.os.RemoteCallbackList; import android.os.RemoteException; import android.service.appprediction.AppPredictionService; import android.util.ArrayMap; Loading @@ -37,7 +37,7 @@ import android.util.Slog; import com.android.internal.annotations.GuardedBy; import com.android.server.infra.AbstractPerUserSystemService; import java.util.ArrayList; import java.util.function.Consumer; /** * Per-user instance of {@link AppPredictionManagerService}. Loading Loading @@ -108,16 +108,11 @@ public class AppPredictionPerUserService extends if (service != null) { service.onCreatePredictionSession(context, sessionId); mSessionInfos.put(sessionId, new AppPredictionSessionInfo(sessionId, context, () -> { synchronized (mLock) { AppPredictionSessionInfo sessionInfo = mSessionInfos.get(sessionId); if (sessionInfo != null) { sessionInfo.removeAllCallbacksLocked(); mSessionInfos.remove(sessionId); if (!mSessionInfos.containsKey(sessionId)) { mSessionInfos.put(sessionId, new AppPredictionSessionInfo(sessionId, context, this::removeAppPredictionSessionInfo)); } } })); } } /** Loading Loading @@ -212,8 +207,7 @@ public class AppPredictionPerUserService extends AppPredictionSessionInfo sessionInfo = mSessionInfos.get(sessionId); if (sessionInfo != null) { sessionInfo.removeAllCallbacksLocked(); mSessionInfos.remove(sessionId); sessionInfo.destroy(); } } } Loading Loading @@ -273,6 +267,15 @@ public class AppPredictionPerUserService extends } } private void removeAppPredictionSessionInfo(AppPredictionSessionId sessionId) { if (isDebug()) { Slog.d(TAG, "removeAppPredictionSessionInfo(): sessionId=" + sessionId); } synchronized (mLock) { mSessionInfos.remove(sessionId); } } @GuardedBy("mLock") @Nullable private RemoteAppPredictionService getRemoteServiceLocked() { Loading @@ -295,55 +298,71 @@ public class AppPredictionPerUserService extends } private static final class AppPredictionSessionInfo { private static final boolean DEBUG = false; // Do not submit with true private final AppPredictionSessionId mSessionId; private final AppPredictionContext mContext; private final ArrayList<IPredictionCallback> mCallbacks = new ArrayList<>(); private final IBinder.DeathRecipient mBinderDeathHandler; private final AppPredictionContext mPredictionContext; private final Consumer<AppPredictionSessionId> mRemoveSessionInfoAction; private final RemoteCallbackList<IPredictionCallback> mCallbacks = new RemoteCallbackList<IPredictionCallback>() { @Override public void onCallbackDied(IPredictionCallback callback) { if (DEBUG) { Slog.d(TAG, "Binder died for session Id=" + mSessionId + " and callback=" + callback.asBinder()); } if (mCallbacks.getRegisteredCallbackCount() == 0) { destroy(); } } }; AppPredictionSessionInfo(AppPredictionSessionId id, AppPredictionContext context, IBinder.DeathRecipient binderDeathHandler) { AppPredictionSessionInfo(AppPredictionSessionId id, AppPredictionContext predictionContext, Consumer<AppPredictionSessionId> removeSessionInfoAction) { if (DEBUG) { Slog.d(TAG, "Creating AppPredictionSessionInfo for session Id=" + id); } mSessionId = id; mContext = context; mBinderDeathHandler = binderDeathHandler; mPredictionContext = predictionContext; mRemoveSessionInfoAction = removeSessionInfoAction; } void addCallbackLocked(IPredictionCallback callback) { if (mBinderDeathHandler != null) { try { callback.asBinder().linkToDeath(mBinderDeathHandler, 0); } catch (RemoteException e) { Slog.e(TAG, "Failed to link to death: " + e); if (DEBUG) { Slog.d(TAG, "Storing callback for session Id=" + mSessionId + " and callback=" + callback.asBinder()); } } mCallbacks.add(callback); mCallbacks.register(callback); } void removeCallbackLocked(IPredictionCallback callback) { if (mBinderDeathHandler != null) { callback.asBinder().unlinkToDeath(mBinderDeathHandler, 0); if (DEBUG) { Slog.d(TAG, "Removing callback for session Id=" + mSessionId + " and callback=" + callback.asBinder()); } mCallbacks.remove(callback); mCallbacks.unregister(callback); } void removeAllCallbacksLocked() { if (mBinderDeathHandler != null) { for (IPredictionCallback callback : mCallbacks) { callback.asBinder().unlinkToDeath(mBinderDeathHandler, 0); } void destroy() { if (DEBUG) { Slog.d(TAG, "Removing all callbacks for session Id=" + mSessionId + " and " + mCallbacks.getRegisteredCallbackCount() + " callbacks."); } mCallbacks.clear(); mCallbacks.kill(); mRemoveSessionInfoAction.accept(mSessionId); } void resurrectSessionLocked(AppPredictionPerUserService service) { if (service.isDebug()) { int callbackCount = mCallbacks.getRegisteredCallbackCount(); if (DEBUG) { Slog.d(TAG, "Resurrecting remote service (" + service.getRemoteServiceLocked() + ") for session Id=" + mSessionId + " and " + mCallbacks.size() + " callbacks."); } service.onCreatePredictionSessionLocked(mContext, mSessionId); for (IPredictionCallback callback : mCallbacks) { service.registerPredictionUpdatesLocked(mSessionId, callback); + callbackCount + " callbacks."); } service.onCreatePredictionSessionLocked(mPredictionContext, mSessionId); mCallbacks.broadcast( callback -> service.registerPredictionUpdatesLocked(mSessionId, callback)); } } } Loading
services/appprediction/java/com/android/server/appprediction/AppPredictionPerUserService.java +61 −42 Original line number Diff line number Diff line Loading @@ -28,7 +28,7 @@ import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.ParceledListSlice; import android.content.pm.ServiceInfo; import android.os.IBinder; import android.os.RemoteCallbackList; import android.os.RemoteException; import android.service.appprediction.AppPredictionService; import android.util.ArrayMap; Loading @@ -37,7 +37,7 @@ import android.util.Slog; import com.android.internal.annotations.GuardedBy; import com.android.server.infra.AbstractPerUserSystemService; import java.util.ArrayList; import java.util.function.Consumer; /** * Per-user instance of {@link AppPredictionManagerService}. Loading Loading @@ -108,16 +108,11 @@ public class AppPredictionPerUserService extends if (service != null) { service.onCreatePredictionSession(context, sessionId); mSessionInfos.put(sessionId, new AppPredictionSessionInfo(sessionId, context, () -> { synchronized (mLock) { AppPredictionSessionInfo sessionInfo = mSessionInfos.get(sessionId); if (sessionInfo != null) { sessionInfo.removeAllCallbacksLocked(); mSessionInfos.remove(sessionId); if (!mSessionInfos.containsKey(sessionId)) { mSessionInfos.put(sessionId, new AppPredictionSessionInfo(sessionId, context, this::removeAppPredictionSessionInfo)); } } })); } } /** Loading Loading @@ -212,8 +207,7 @@ public class AppPredictionPerUserService extends AppPredictionSessionInfo sessionInfo = mSessionInfos.get(sessionId); if (sessionInfo != null) { sessionInfo.removeAllCallbacksLocked(); mSessionInfos.remove(sessionId); sessionInfo.destroy(); } } } Loading Loading @@ -273,6 +267,15 @@ public class AppPredictionPerUserService extends } } private void removeAppPredictionSessionInfo(AppPredictionSessionId sessionId) { if (isDebug()) { Slog.d(TAG, "removeAppPredictionSessionInfo(): sessionId=" + sessionId); } synchronized (mLock) { mSessionInfos.remove(sessionId); } } @GuardedBy("mLock") @Nullable private RemoteAppPredictionService getRemoteServiceLocked() { Loading @@ -295,55 +298,71 @@ public class AppPredictionPerUserService extends } private static final class AppPredictionSessionInfo { private static final boolean DEBUG = false; // Do not submit with true private final AppPredictionSessionId mSessionId; private final AppPredictionContext mContext; private final ArrayList<IPredictionCallback> mCallbacks = new ArrayList<>(); private final IBinder.DeathRecipient mBinderDeathHandler; private final AppPredictionContext mPredictionContext; private final Consumer<AppPredictionSessionId> mRemoveSessionInfoAction; private final RemoteCallbackList<IPredictionCallback> mCallbacks = new RemoteCallbackList<IPredictionCallback>() { @Override public void onCallbackDied(IPredictionCallback callback) { if (DEBUG) { Slog.d(TAG, "Binder died for session Id=" + mSessionId + " and callback=" + callback.asBinder()); } if (mCallbacks.getRegisteredCallbackCount() == 0) { destroy(); } } }; AppPredictionSessionInfo(AppPredictionSessionId id, AppPredictionContext context, IBinder.DeathRecipient binderDeathHandler) { AppPredictionSessionInfo(AppPredictionSessionId id, AppPredictionContext predictionContext, Consumer<AppPredictionSessionId> removeSessionInfoAction) { if (DEBUG) { Slog.d(TAG, "Creating AppPredictionSessionInfo for session Id=" + id); } mSessionId = id; mContext = context; mBinderDeathHandler = binderDeathHandler; mPredictionContext = predictionContext; mRemoveSessionInfoAction = removeSessionInfoAction; } void addCallbackLocked(IPredictionCallback callback) { if (mBinderDeathHandler != null) { try { callback.asBinder().linkToDeath(mBinderDeathHandler, 0); } catch (RemoteException e) { Slog.e(TAG, "Failed to link to death: " + e); if (DEBUG) { Slog.d(TAG, "Storing callback for session Id=" + mSessionId + " and callback=" + callback.asBinder()); } } mCallbacks.add(callback); mCallbacks.register(callback); } void removeCallbackLocked(IPredictionCallback callback) { if (mBinderDeathHandler != null) { callback.asBinder().unlinkToDeath(mBinderDeathHandler, 0); if (DEBUG) { Slog.d(TAG, "Removing callback for session Id=" + mSessionId + " and callback=" + callback.asBinder()); } mCallbacks.remove(callback); mCallbacks.unregister(callback); } void removeAllCallbacksLocked() { if (mBinderDeathHandler != null) { for (IPredictionCallback callback : mCallbacks) { callback.asBinder().unlinkToDeath(mBinderDeathHandler, 0); } void destroy() { if (DEBUG) { Slog.d(TAG, "Removing all callbacks for session Id=" + mSessionId + " and " + mCallbacks.getRegisteredCallbackCount() + " callbacks."); } mCallbacks.clear(); mCallbacks.kill(); mRemoveSessionInfoAction.accept(mSessionId); } void resurrectSessionLocked(AppPredictionPerUserService service) { if (service.isDebug()) { int callbackCount = mCallbacks.getRegisteredCallbackCount(); if (DEBUG) { Slog.d(TAG, "Resurrecting remote service (" + service.getRemoteServiceLocked() + ") for session Id=" + mSessionId + " and " + mCallbacks.size() + " callbacks."); } service.onCreatePredictionSessionLocked(mContext, mSessionId); for (IPredictionCallback callback : mCallbacks) { service.registerPredictionUpdatesLocked(mSessionId, callback); + callbackCount + " callbacks."); } service.onCreatePredictionSessionLocked(mPredictionContext, mSessionId); mCallbacks.broadcast( callback -> service.registerPredictionUpdatesLocked(mSessionId, callback)); } } }