Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 51600446 authored by Tim Yu's avatar Tim Yu
Browse files

Catch all exceptions in AutofillManagerService methods.

This prevents exceptions from propagating, which
would have resulted in Autofill server timing out, which would cause various apps to ANR.

Bug: 278209634
Fixes: 285041619
Test: atest CtsAutoFillServiceTestCases
Change-Id: Ia2afd2e483587796ed62b32bc0aba1bc48b371f9
parent 3502d6ba
Loading
Loading
Loading
Loading
+9 −8
Original line number Diff line number Diff line
@@ -2065,7 +2065,7 @@ public final class AutofillManager {
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        } catch (SyncResultReceiver.TimeoutException e) {
            throw new RuntimeException("Fail to get enabled autofill services status.");
            throw new RuntimeException("Fail to get enabled autofill services status. " + e);
        }
    }

@@ -2084,7 +2084,7 @@ public final class AutofillManager {
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        } catch (SyncResultReceiver.TimeoutException e) {
            throw new RuntimeException("Fail to get autofill services component name.");
            throw new RuntimeException("Fail to get autofill services component name. " + e);
        }
    }

@@ -2111,7 +2111,7 @@ public final class AutofillManager {
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        } catch (SyncResultReceiver.TimeoutException e) {
            throw new RuntimeException("Fail to get user data id for field classification.");
            throw new RuntimeException("Fail to get user data id for field classification. " + e);
        }
    }

@@ -2134,7 +2134,7 @@ public final class AutofillManager {
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        } catch (SyncResultReceiver.TimeoutException e) {
            throw new RuntimeException("Fail to get user data for field classification.");
            throw new RuntimeException("Fail to get user data for field classification. " + e);
        }
    }

@@ -2174,7 +2174,7 @@ public final class AutofillManager {
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        } catch (SyncResultReceiver.TimeoutException e) {
            throw new RuntimeException("Fail to get field classification enabled status.");
            throw new RuntimeException("Fail to get field classification enabled status. " + e);
        }
    }

@@ -2198,7 +2198,7 @@ public final class AutofillManager {
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        } catch (SyncResultReceiver.TimeoutException e) {
            throw new RuntimeException("Fail to get default field classification algorithm.");
            throw new RuntimeException("Fail to get default field classification algorithm. " + e);
        }
    }

@@ -2220,7 +2220,8 @@ public final class AutofillManager {
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        } catch (SyncResultReceiver.TimeoutException e) {
            throw new RuntimeException("Fail to get available field classification algorithms.");
            throw new
                RuntimeException("Fail to get available field classification algorithms. " + e);
        }
    }

@@ -2244,7 +2245,7 @@ public final class AutofillManager {
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        } catch (SyncResultReceiver.TimeoutException e) {
            throw new RuntimeException("Fail to get autofill supported status.");
            throw new RuntimeException("Fail to get autofill supported status. " + e);
        }
    }

+185 −107
Original line number Diff line number Diff line
@@ -63,6 +63,7 @@ import android.text.TextUtils;
import android.text.TextUtils.SimpleStringSplitter;
import android.util.ArrayMap;
import android.util.LocalLog;
import android.util.Log;
import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
@@ -1525,6 +1526,7 @@ public final class AutofillManagerService
        public void addClient(IAutoFillManagerClient client, ComponentName componentName,
                int userId, IResultReceiver receiver) {
            int flags = 0;
            try {
                synchronized (mLock) {
                    final int enabledFlags = getServiceForUserLocked(userId).addClientLocked(client,
                            componentName);
@@ -1538,8 +1540,13 @@ public final class AutofillManagerService
                        flags |= AutofillManager.FLAG_ADD_CLIENT_VERBOSE;
                    }
                }
            } catch (Exception ex) {
                // Don't do anything, send back default flags
                Log.wtf(TAG, "addClient(): failed " + ex.toString());
            } finally {
                send(receiver, flags);
            }
        }

        @Override
        public void removeClient(IAutoFillManagerClient client, int userId) {
@@ -1613,8 +1620,8 @@ public final class AutofillManagerService
        @Override
        public void getFillEventHistory(@NonNull IResultReceiver receiver) throws RemoteException {
            final int userId = UserHandle.getCallingUserId();

            FillEventHistory fillEventHistory = null;
            try {
                synchronized (mLock) {
                    final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
                    if (service != null) {
@@ -1623,14 +1630,20 @@ public final class AutofillManagerService
                        Slog.v(TAG, "getFillEventHistory(): no service for " + userId);
                    }
                }
            } catch (Exception ex) {
                // Do not raise the exception, just send back the null response
                Log.wtf(TAG, "getFillEventHistory(): failed " + ex.toString());
            } finally {
                send(receiver, fillEventHistory);
            }
        }

        @Override
        public void getUserData(@NonNull IResultReceiver receiver) throws RemoteException {
            final int userId = UserHandle.getCallingUserId();

            UserData userData = null;

            try {
                final int userId = UserHandle.getCallingUserId();
                synchronized (mLock) {
                    final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
                    if (service != null) {
@@ -1639,14 +1652,20 @@ public final class AutofillManagerService
                        Slog.v(TAG, "getUserData(): no service for " + userId);
                    }
                }
            } catch (Exception ex) {
                // Do not raise the exception, just send back the null response
                Log.wtf(TAG, "getUserData(): failed " + ex.toString());
            } finally {
                send(receiver, userData);
            }
        }

        @Override
        public void getUserDataId(@NonNull IResultReceiver receiver) throws RemoteException {
            final int userId = UserHandle.getCallingUserId();
            UserData userData = null;
            final int userId = UserHandle.getCallingUserId();

            try {
                synchronized (mLock) {
                    final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
                    if (service != null) {
@@ -1655,9 +1674,14 @@ public final class AutofillManagerService
                        Slog.v(TAG, "getUserDataId(): no service for " + userId);
                    }
                }
            } catch (Exception ex) {
                // Do not raie the exception, just send back null
                Log.wtf(TAG, "getUserDataId(): failed " + ex.toString());
            } finally {
                final String userDataId = userData == null ? null : userData.getId();
                send(receiver, userDataId);
            }
        }

        @Override
        public void setUserData(UserData userData) throws RemoteException {
@@ -1676,9 +1700,9 @@ public final class AutofillManagerService
        @Override
        public void isFieldClassificationEnabled(@NonNull IResultReceiver receiver)
                throws RemoteException {
            final int userId = UserHandle.getCallingUserId();
            boolean enabled = false;

            try {
                final int userId = UserHandle.getCallingUserId();
                synchronized (mLock) {
                    final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
                    if (service != null) {
@@ -1687,15 +1711,21 @@ public final class AutofillManagerService
                        Slog.v(TAG, "isFieldClassificationEnabled(): no service for " + userId);
                    }
                }
            } catch (Exception ex) {
                // Do not raise the exception, just send back false
                Log.wtf(TAG, "isFieldClassificationEnabled(): failed " + ex.toString());
            } finally {
                send(receiver, enabled);
            }
        }

        @Override
        public void getDefaultFieldClassificationAlgorithm(@NonNull IResultReceiver receiver)
                throws RemoteException {
            final int userId = UserHandle.getCallingUserId();
            String algorithm = null;

            try {
                final int userId = UserHandle.getCallingUserId();
                synchronized (mLock) {
                    final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
                    if (service != null) {
@@ -1706,16 +1736,23 @@ public final class AutofillManagerService
                        }
                    }
                }
            } catch (Exception ex) {
                // Do not raise the exception, just send back null
                Log.wtf(TAG, "getDefaultFieldClassificationAlgorithm(): failed " + ex.toString());
            } finally {
                send(receiver, algorithm);
            }

        }

        @Override
        public void setAugmentedAutofillWhitelist(@Nullable List<String> packages,
                @Nullable List<ComponentName> activities, @NonNull IResultReceiver receiver)
                throws RemoteException {
            final int userId = UserHandle.getCallingUserId();
            boolean ok = false;

            boolean ok;
            try {
                final int userId = UserHandle.getCallingUserId();
                synchronized (mLock) {
                    final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
                    if (service != null) {
@@ -1723,40 +1760,56 @@ public final class AutofillManagerService
                                getCallingUid());
                    } else {
                        if (sVerbose) {
                        Slog.v(TAG, "setAugmentedAutofillWhitelist(): no service for " + userId);
                            Slog.v(TAG, "setAugmentedAutofillWhitelist(): no service for "
                                    + userId);
                        }
                    ok = false;
                    }
                }
            } catch (Exception ex) {
                // Do not raise the exception, return the default value
                Log.wtf(TAG, "setAugmentedAutofillWhitelist(): failed " + ex.toString());
            } finally {
                send(receiver,
                    ok ? AutofillManager.RESULT_OK : AutofillManager.RESULT_CODE_NOT_SERVICE);
                        ok ? AutofillManager.RESULT_OK
                            : AutofillManager.RESULT_CODE_NOT_SERVICE);
            }
        }

        @Override
        public void getAvailableFieldClassificationAlgorithms(@NonNull IResultReceiver receiver)
                throws RemoteException {
            final int userId = UserHandle.getCallingUserId();
            String[] algorithms = null;

            try {
                final int userId = UserHandle.getCallingUserId();
                synchronized (mLock) {
                    final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
                    if (service != null) {
                    algorithms = service.getAvailableFieldClassificationAlgorithms(getCallingUid());
                        algorithms = service
                            .getAvailableFieldClassificationAlgorithms(getCallingUid());
                    } else {
                        if (sVerbose) {
                            Slog.v(TAG, "getAvailableFcAlgorithms(): no service for " + userId);
                        }
                    }
                }
            } catch (Exception ex) {
                // Do not raise the exception, return null
                Log.wtf(TAG, "getAvailableFieldClassificationAlgorithms(): failed "
                        + ex.toString());
            } finally {
                send(receiver, algorithms);
            }
        }

        @Override
        public void getAutofillServiceComponentName(@NonNull IResultReceiver receiver)
                throws RemoteException {
            ComponentName componentName = null;

            try {
                final int userId = UserHandle.getCallingUserId();

            ComponentName componentName = null;
                synchronized (mLock) {
                    final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
                    if (service != null) {
@@ -1765,18 +1818,24 @@ public final class AutofillManagerService
                        Slog.v(TAG, "getAutofillServiceComponentName(): no service for " + userId);
                    }
                }
            } catch (Exception ex) {
                Log.wtf(TAG, "getAutofillServiceComponentName(): failed " + ex.toString());
            } finally {
                send(receiver, componentName);
            }
        }

        @Override
        public void restoreSession(int sessionId, @NonNull IBinder activityToken,
                @NonNull IBinder appCallback, @NonNull IResultReceiver receiver)
                throws RemoteException {
            final int userId = UserHandle.getCallingUserId();
            boolean restored = false;

            try {
                Objects.requireNonNull(activityToken, "activityToken");
                Objects.requireNonNull(appCallback, "appCallback");

            boolean restored = false;
                final int userId = UserHandle.getCallingUserId();
                synchronized (mLock) {
                    final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
                    if (service != null) {
@@ -1786,8 +1845,13 @@ public final class AutofillManagerService
                        Slog.v(TAG, "restoreSession(): no service for " + userId);
                    }
                }
            } catch (Exception ex) {
                // Do not propagate exception, send back status
                Log.wtf(TAG, "restoreSession(): failed " + ex.toString());
            } finally {
                send(receiver, restored);
            }
        }

        @Override
        public void updateSession(int sessionId, AutofillId autoFillId, Rect bounds,
@@ -1855,22 +1919,36 @@ public final class AutofillManagerService
        @Override
        public void isServiceSupported(int userId, @NonNull IResultReceiver receiver) {
            boolean supported = false;

            try {
                synchronized (mLock) {
                    supported = !isDisabledLocked(userId);
                }
            } catch (Exception ex) {
                // Do not propagate exception
                Log.wtf(TAG, "isServiceSupported(): failed " + ex.toString());
            } finally {
                send(receiver, supported);
            }
        }

        @Override
        public void isServiceEnabled(int userId, @NonNull String packageName,
                @NonNull IResultReceiver receiver) {
            boolean enabled = false;

            try {
                synchronized (mLock) {
                    final AutofillManagerServiceImpl service = getServiceForUserLocked(userId);
                    enabled = Objects.equals(packageName, service.getServicePackageName());
                }
            } catch (Exception ex) {
                // Do not propagate exception
                Log.wtf(TAG, "isServiceEnabled(): failed " + ex.toString());
            } finally {
                send(receiver, enabled);
            }
        }

        @Override
        public void onPendingSaveUi(int operation, IBinder token) {