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

Commit 7ec28e85 authored by Svetoslav's avatar Svetoslav
Browse files

Do not call out of the settings provider with a lock held

bug:20443441

Change-Id: I704520b75f5deaeeb1b4098cda0783c667e8cdd1
parent d8ecc5ae
Loading
Loading
Loading
Loading
+276 −255
Original line number Diff line number Diff line
@@ -201,14 +201,14 @@ public class SettingsProvider extends ContentProvider {
    @GuardedBy("mLock")
    private SettingsRegistry mSettingsRegistry;

    @GuardedBy("mLock")
    private UserManager mUserManager;
    // We have to call in the user manager with no lock held,
    private volatile UserManager mUserManager;

    @GuardedBy("mLock")
    private AppOpsManager mAppOpsManager;
    // We have to call in the app ops manager with no lock held,
    private volatile AppOpsManager mAppOpsManager;

    @GuardedBy("mLock")
    private PackageManager mPackageManager;
    // We have to call in the package manager with no lock held,
    private volatile PackageManager mPackageManager;

    @Override
    public boolean onCreate() {
@@ -224,44 +224,46 @@ public class SettingsProvider extends ContentProvider {

    @Override
    public Bundle call(String method, String name, Bundle args) {
        synchronized (mLock) {
        final int requestingUserId = getRequestingUserId(args);
        switch (method) {
            case Settings.CALL_METHOD_GET_GLOBAL: {
                    Setting setting = getGlobalSettingLocked(name);
                Setting setting = getGlobalSetting(name);
                return packageValueForCallResult(setting);
            }

            case Settings.CALL_METHOD_GET_SECURE: {
                    Setting setting = getSecureSettingLocked(name, requestingUserId);
                Setting setting = getSecureSetting(name, requestingUserId);
                return packageValueForCallResult(setting);
            }

            case Settings.CALL_METHOD_GET_SYSTEM: {
                    Setting setting = getSystemSettingLocked(name, requestingUserId);
                Setting setting = getSystemSetting(name, requestingUserId);
                return packageValueForCallResult(setting);
            }

            case Settings.CALL_METHOD_PUT_GLOBAL: {
                String value = getSettingValue(args);
                    insertGlobalSettingLocked(name, value, requestingUserId);
                } break;
                insertGlobalSetting(name, value, requestingUserId);
                break;
            }

            case Settings.CALL_METHOD_PUT_SECURE: {
                String value = getSettingValue(args);
                    insertSecureSettingLocked(name, value, requestingUserId);
                } break;
                insertSecureSetting(name, value, requestingUserId);
                break;
            }

            case Settings.CALL_METHOD_PUT_SYSTEM: {
                String value = getSettingValue(args);
                    insertSystemSettingLocked(name, value, requestingUserId);
                } break;
                insertSystemSetting(name, value, requestingUserId);
                break;
            }

            default: {
                Slog.w(LOG_TAG, "call() with invalid method: " + method);
            } break;
        }
        }

        return null;
    }

@@ -290,34 +292,33 @@ public class SettingsProvider extends ContentProvider {
            return new MatrixCursor(normalizedProjection, 0);
        }

        synchronized (mLock) {
        switch (args.table) {
            case TABLE_GLOBAL: {
                if (args.name != null) {
                        Setting setting = getGlobalSettingLocked(args.name);
                    Setting setting = getGlobalSetting(args.name);
                    return packageSettingForQuery(setting, normalizedProjection);
                } else {
                        return getAllGlobalSettingsLocked(projection);
                    return getAllGlobalSettings(projection);
                }
            }

            case TABLE_SECURE: {
                final int userId = UserHandle.getCallingUserId();
                if (args.name != null) {
                        Setting setting = getSecureSettingLocked(args.name, userId);
                    Setting setting = getSecureSetting(args.name, userId);
                    return packageSettingForQuery(setting, normalizedProjection);
                } else {
                        return getAllSecureSettingsLocked(userId, projection);
                    return getAllSecureSettings(userId, projection);
                }
            }

            case TABLE_SYSTEM: {
                final int userId = UserHandle.getCallingUserId();
                if (args.name != null) {
                        Setting setting = getSystemSettingLocked(args.name, userId);
                    Setting setting = getSystemSetting(args.name, userId);
                    return packageSettingForQuery(setting, normalizedProjection);
                } else {
                        return getAllSystemSettingsLocked(userId, projection);
                    return getAllSystemSettings(userId, projection);
                }
            }

@@ -326,7 +327,6 @@ public class SettingsProvider extends ContentProvider {
            }
        }
    }
    }

    @Override
    public Uri insert(Uri uri, ContentValues values) {
@@ -348,22 +348,21 @@ public class SettingsProvider extends ContentProvider {

        String value = values.getAsString(Settings.Secure.VALUE);

        synchronized (mLock) {
        switch (table) {
            case TABLE_GLOBAL: {
                    if (insertGlobalSettingLocked(name, value, UserHandle.getCallingUserId())) {
                if (insertGlobalSetting(name, value, UserHandle.getCallingUserId())) {
                    return Uri.withAppendedPath(Settings.Global.CONTENT_URI, name);
                }
            } break;

            case TABLE_SECURE: {
                    if (insertSecureSettingLocked(name, value, UserHandle.getCallingUserId())) {
                if (insertSecureSetting(name, value, UserHandle.getCallingUserId())) {
                    return Uri.withAppendedPath(Settings.Secure.CONTENT_URI, name);
                }
            } break;

            case TABLE_SYSTEM: {
                    if (insertSystemSettingLocked(name, value, UserHandle.getCallingUserId())) {
                if (insertSystemSetting(name, value, UserHandle.getCallingUserId())) {
                    return Uri.withAppendedPath(Settings.System.CONTENT_URI, name);
                }
            } break;
@@ -372,7 +371,6 @@ public class SettingsProvider extends ContentProvider {
                throw new IllegalArgumentException("Bad Uri path:" + uri);
            }
        }
        }

        return null;
    }
@@ -412,21 +410,21 @@ public class SettingsProvider extends ContentProvider {
            return 0;
        }

        synchronized (mLock) {

        switch (args.table) {
            case TABLE_GLOBAL: {
                final int userId = UserHandle.getCallingUserId();
                    return deleteGlobalSettingLocked(args.name, userId) ? 1 : 0;
                return deleteGlobalSetting(args.name, userId) ? 1 : 0;
            }

            case TABLE_SECURE: {
                final int userId = UserHandle.getCallingUserId();
                    return deleteSecureSettingLocked(args.name, userId) ? 1 : 0;
                return deleteSecureSetting(args.name, userId) ? 1 : 0;
            }

            case TABLE_SYSTEM: {
                final int userId = UserHandle.getCallingUserId();
                    return deleteSystemSettingLocked(args.name, userId) ? 1 : 0;
                return deleteSystemSetting(args.name, userId) ? 1 : 0;
            }

            default: {
@@ -434,7 +432,6 @@ public class SettingsProvider extends ContentProvider {
            }
        }
    }
    }

    @Override
    public int update(Uri uri, ContentValues values, String where, String[] whereArgs) {
@@ -454,21 +451,20 @@ public class SettingsProvider extends ContentProvider {
            return 0;
        }

        synchronized (mLock) {
        switch (args.table) {
            case TABLE_GLOBAL: {
                final int userId = UserHandle.getCallingUserId();
                    return updateGlobalSettingLocked(args.name, value, userId) ? 1 : 0;
                return updateGlobalSetting(args.name, value, userId) ? 1 : 0;
            }

            case TABLE_SECURE: {
                final int userId = UserHandle.getCallingUserId();
                    return updateSecureSettingLocked(args.name, value, userId) ? 1 : 0;
                return updateSecureSetting(args.name, value, userId) ? 1 : 0;
            }

            case TABLE_SYSTEM: {
                final int userId = UserHandle.getCallingUserId();
                    return updateSystemSettingLocked(args.name, value, userId) ? 1 : 0;
                return updateSystemSetting(args.name, value, userId) ? 1 : 0;
            }

            default: {
@@ -476,7 +472,6 @@ public class SettingsProvider extends ContentProvider {
            }
        }
    }
    }

    @Override
    public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
@@ -504,18 +499,18 @@ public class SettingsProvider extends ContentProvider {
    private void dumpForUser(int userId, PrintWriter pw) {
        if (userId == UserHandle.USER_OWNER) {
            pw.println("GLOBAL SETTINGS (user " + userId + ")");
            Cursor globalCursor = getAllGlobalSettingsLocked(ALL_COLUMNS);
            Cursor globalCursor = getAllGlobalSettings(ALL_COLUMNS);
            dumpSettings(globalCursor, pw);
            pw.println();
        }

        pw.println("SECURE SETTINGS (user " + userId + ")");
        Cursor secureCursor = getAllSecureSettingsLocked(userId, ALL_COLUMNS);
        Cursor secureCursor = getAllSecureSettings(userId, ALL_COLUMNS);
        dumpSettings(secureCursor, pw);
        pw.println();

        pw.println("SYSTEM SETTINGS (user " + userId + ")");
        Cursor systemCursor = getAllSystemSettingsLocked(userId, ALL_COLUMNS);
        Cursor systemCursor = getAllSystemSettings(userId, ALL_COLUMNS);
        dumpSettings(systemCursor, pw);
        pw.println();
    }
@@ -575,11 +570,12 @@ public class SettingsProvider extends ContentProvider {
                UserHandle.ALL, true);
    }

    private Cursor getAllGlobalSettingsLocked(String[] projection) {
    private Cursor getAllGlobalSettings(String[] projection) {
        if (DEBUG) {
            Slog.v(LOG_TAG, "getAllGlobalSettingsLocked()");
            Slog.v(LOG_TAG, "getAllGlobalSettings()");
        }

        synchronized (mLock) {
            // Get the settings.
            SettingsState settingsState = mSettingsRegistry.getSettingsLocked(
                    SettingsRegistry.SETTINGS_TYPE_GLOBAL, UserHandle.USER_OWNER);
@@ -600,39 +596,42 @@ public class SettingsProvider extends ContentProvider {

            return result;
        }
    }

    private Setting getGlobalSettingLocked(String name) {
    private Setting getGlobalSetting(String name) {
        if (DEBUG) {
            Slog.v(LOG_TAG, "getGlobalSetting(" + name + ")");
        }

        // Get the value.
        synchronized (mLock) {
            return mSettingsRegistry.getSettingLocked(SettingsRegistry.SETTINGS_TYPE_GLOBAL,
                    UserHandle.USER_OWNER, name);
        }
    }

    private boolean updateGlobalSettingLocked(String name, String value, int requestingUserId) {
    private boolean updateGlobalSetting(String name, String value, int requestingUserId) {
        if (DEBUG) {
            Slog.v(LOG_TAG, "updateGlobalSettingLocked(" + name + ", " + value + ")");
            Slog.v(LOG_TAG, "updateGlobalSetting(" + name + ", " + value + ")");
        }
        return mutateGlobalSettingLocked(name, value, requestingUserId, MUTATION_OPERATION_UPDATE);
        return mutateGlobalSetting(name, value, requestingUserId, MUTATION_OPERATION_UPDATE);
    }

    private boolean insertGlobalSettingLocked(String name, String value, int requestingUserId) {
    private boolean insertGlobalSetting(String name, String value, int requestingUserId) {
        if (DEBUG) {
            Slog.v(LOG_TAG, "insertGlobalSettingLocked(" + name + ", " + value + ")");
            Slog.v(LOG_TAG, "insertGlobalSetting(" + name + ", " + value + ")");
        }
        return mutateGlobalSettingLocked(name, value, requestingUserId, MUTATION_OPERATION_INSERT);
        return mutateGlobalSetting(name, value, requestingUserId, MUTATION_OPERATION_INSERT);
    }

    private boolean deleteGlobalSettingLocked(String name, int requestingUserId) {
    private boolean deleteGlobalSetting(String name, int requestingUserId) {
        if (DEBUG) {
            Slog.v(LOG_TAG, "deleteGlobalSettingLocked(" + name + ")");
        }
        return mutateGlobalSettingLocked(name, null, requestingUserId, MUTATION_OPERATION_DELETE);
        return mutateGlobalSetting(name, null, requestingUserId, MUTATION_OPERATION_DELETE);
    }

    private boolean mutateGlobalSettingLocked(String name, String value, int requestingUserId,
    private boolean mutateGlobalSetting(String name, String value, int requestingUserId,
            int operation) {
        // Make sure the caller can change the settings - treated as secure.
        enforceWritePermission(Manifest.permission.WRITE_SECURE_SETTINGS);
@@ -651,9 +650,11 @@ public class SettingsProvider extends ContentProvider {
        }

        // Perform the mutation.
        synchronized (mLock) {
            switch (operation) {
                case MUTATION_OPERATION_INSERT: {
                return mSettingsRegistry.insertSettingLocked(SettingsRegistry.SETTINGS_TYPE_GLOBAL,
                    return mSettingsRegistry
                            .insertSettingLocked(SettingsRegistry.SETTINGS_TYPE_GLOBAL,
                                    UserHandle.USER_OWNER, name, value, getCallingPackage());
                }

@@ -664,15 +665,17 @@ public class SettingsProvider extends ContentProvider {
                }

                case MUTATION_OPERATION_UPDATE: {
                return mSettingsRegistry.updateSettingLocked(SettingsRegistry.SETTINGS_TYPE_GLOBAL,
                    return mSettingsRegistry
                            .updateSettingLocked(SettingsRegistry.SETTINGS_TYPE_GLOBAL,
                                    UserHandle.USER_OWNER, name, value, getCallingPackage());
                }
            }
        }

        return false;
    }

    private Cursor getAllSecureSettingsLocked(int userId, String[] projection) {
    private Cursor getAllSecureSettings(int userId, String[] projection) {
        if (DEBUG) {
            Slog.v(LOG_TAG, "getAllSecureSettings(" + userId + ")");
        }
@@ -680,6 +683,7 @@ public class SettingsProvider extends ContentProvider {
        // Resolve the userId on whose behalf the call is made.
        final int callingUserId = resolveCallingUserIdEnforcingPermissionsLocked(userId);

        synchronized (mLock) {
            List<String> names = mSettingsRegistry.getSettingsNamesLocked(
                    SettingsRegistry.SETTINGS_TYPE_SECURE, callingUserId);

@@ -690,9 +694,9 @@ public class SettingsProvider extends ContentProvider {

            for (int i = 0; i < nameCount; i++) {
                String name = names.get(i);

                // Determine the owning user as some profile settings are cloned from the parent.
            final int owningUserId = resolveOwningUserIdForSecureSettingLocked(callingUserId, name);
                final int owningUserId = resolveOwningUserIdForSecureSettingLocked(callingUserId,
                        name);

                // Special case for location (sigh).
                if (isLocationProvidersAllowedRestricted(name, callingUserId, owningUserId)) {
@@ -706,8 +710,9 @@ public class SettingsProvider extends ContentProvider {

            return result;
        }
    }

    private Setting getSecureSettingLocked(String name, int requestingUserId) {
    private Setting getSecureSetting(String name, int requestingUserId) {
        if (DEBUG) {
            Slog.v(LOG_TAG, "getSecureSetting(" + name + ", " + requestingUserId + ")");
        }
@@ -724,37 +729,39 @@ public class SettingsProvider extends ContentProvider {
        }

        // Get the value.
        synchronized (mLock) {
            return mSettingsRegistry.getSettingLocked(SettingsRegistry.SETTINGS_TYPE_SECURE,
                    owningUserId, name);
        }
    }

    private boolean insertSecureSettingLocked(String name, String value, int requestingUserId) {
    private boolean insertSecureSetting(String name, String value, int requestingUserId) {
        if (DEBUG) {
            Slog.v(LOG_TAG, "insertSecureSettingLocked(" + name + ", " + value + ", "
            Slog.v(LOG_TAG, "insertSecureSetting(" + name + ", " + value + ", "
                    + requestingUserId + ")");
        }

        return mutateSecureSettingLocked(name, value, requestingUserId, MUTATION_OPERATION_INSERT);
        return mutateSecureSetting(name, value, requestingUserId, MUTATION_OPERATION_INSERT);
    }

    private boolean deleteSecureSettingLocked(String name, int requestingUserId) {
    private boolean deleteSecureSetting(String name, int requestingUserId) {
        if (DEBUG) {
            Slog.v(LOG_TAG, "deleteSecureSettingLocked(" + name + ", " + requestingUserId + ")");
            Slog.v(LOG_TAG, "deleteSecureSetting(" + name + ", " + requestingUserId + ")");
        }

        return mutateSecureSettingLocked(name, null, requestingUserId, MUTATION_OPERATION_DELETE);
        return mutateSecureSetting(name, null, requestingUserId, MUTATION_OPERATION_DELETE);
    }

    private boolean updateSecureSettingLocked(String name, String value, int requestingUserId) {
    private boolean updateSecureSetting(String name, String value, int requestingUserId) {
        if (DEBUG) {
            Slog.v(LOG_TAG, "updateSecureSettingLocked(" + name + ", " + value + ", "
            Slog.v(LOG_TAG, "updateSecureSetting(" + name + ", " + value + ", "
                    + requestingUserId + ")");
        }

        return mutateSecureSettingLocked(name, value, requestingUserId, MUTATION_OPERATION_UPDATE);
        return mutateSecureSetting(name, value, requestingUserId, MUTATION_OPERATION_UPDATE);
    }

    private boolean mutateSecureSettingLocked(String name, String value, int requestingUserId,
    private boolean mutateSecureSetting(String name, String value, int requestingUserId,
            int operation) {
        // Make sure the caller can change the settings.
        enforceWritePermission(Manifest.permission.WRITE_SECURE_SETTINGS);
@@ -786,9 +793,11 @@ public class SettingsProvider extends ContentProvider {
        }

        // Mutate the value.
        synchronized (mLock) {
            switch (operation) {
                case MUTATION_OPERATION_INSERT: {
                return mSettingsRegistry.insertSettingLocked(SettingsRegistry.SETTINGS_TYPE_SECURE,
                    return mSettingsRegistry
                            .insertSettingLocked(SettingsRegistry.SETTINGS_TYPE_SECURE,
                                    owningUserId, name, value, getCallingPackage());
                }

@@ -799,22 +808,25 @@ public class SettingsProvider extends ContentProvider {
                }

                case MUTATION_OPERATION_UPDATE: {
                return mSettingsRegistry.updateSettingLocked(SettingsRegistry.SETTINGS_TYPE_SECURE,
                    return mSettingsRegistry
                            .updateSettingLocked(SettingsRegistry.SETTINGS_TYPE_SECURE,
                                    owningUserId, name, value, getCallingPackage());
                }
            }
        }

        return false;
    }

    private Cursor getAllSystemSettingsLocked(int userId, String[] projection) {
    private Cursor getAllSystemSettings(int userId, String[] projection) {
        if (DEBUG) {
            Slog.v(LOG_TAG, "getAllSecureSystemLocked(" + userId + ")");
            Slog.v(LOG_TAG, "getAllSecureSystem(" + userId + ")");
        }

        // Resolve the userId on whose behalf the call is made.
        final int callingUserId = resolveCallingUserIdEnforcingPermissionsLocked(userId);

        synchronized (mLock) {
            List<String> names = mSettingsRegistry.getSettingsNamesLocked(
                    SettingsRegistry.SETTINGS_TYPE_SYSTEM, callingUserId);

@@ -827,7 +839,8 @@ public class SettingsProvider extends ContentProvider {
                String name = names.get(i);

                // Determine the owning user as some profile settings are cloned from the parent.
            final int owningUserId = resolveOwningUserIdForSystemSettingLocked(callingUserId, name);
                final int owningUserId = resolveOwningUserIdForSystemSettingLocked(callingUserId,
                        name);

                Setting setting = mSettingsRegistry.getSettingLocked(
                        SettingsRegistry.SETTINGS_TYPE_SYSTEM, owningUserId, name);
@@ -836,8 +849,9 @@ public class SettingsProvider extends ContentProvider {

            return result;
        }
    }

    private Setting getSystemSettingLocked(String name, int requestingUserId) {
    private Setting getSystemSetting(String name, int requestingUserId) {
        if (DEBUG) {
            Slog.v(LOG_TAG, "getSystemSetting(" + name + ", " + requestingUserId + ")");
        }
@@ -849,37 +863,39 @@ public class SettingsProvider extends ContentProvider {
        final int owningUserId = resolveOwningUserIdForSystemSettingLocked(callingUserId, name);

        // Get the value.
        synchronized (mLock) {
            return mSettingsRegistry.getSettingLocked(SettingsRegistry.SETTINGS_TYPE_SYSTEM,
                    owningUserId, name);
        }
    }

    private boolean insertSystemSettingLocked(String name, String value, int requestingUserId) {
    private boolean insertSystemSetting(String name, String value, int requestingUserId) {
        if (DEBUG) {
            Slog.v(LOG_TAG, "insertSystemSettingLocked(" + name + ", " + value + ", "
            Slog.v(LOG_TAG, "insertSystemSetting(" + name + ", " + value + ", "
                    + requestingUserId + ")");
        }

        return mutateSystemSettingLocked(name, value, requestingUserId, MUTATION_OPERATION_INSERT);
        return mutateSystemSetting(name, value, requestingUserId, MUTATION_OPERATION_INSERT);
    }

    private boolean deleteSystemSettingLocked(String name, int requestingUserId) {
    private boolean deleteSystemSetting(String name, int requestingUserId) {
        if (DEBUG) {
            Slog.v(LOG_TAG, "deleteSystemSettingLocked(" + name + ", " + requestingUserId + ")");
            Slog.v(LOG_TAG, "deleteSystemSetting(" + name + ", " + requestingUserId + ")");
        }

        return mutateSystemSettingLocked(name, null, requestingUserId, MUTATION_OPERATION_DELETE);
        return mutateSystemSetting(name, null, requestingUserId, MUTATION_OPERATION_DELETE);
    }

    private boolean updateSystemSettingLocked(String name, String value, int requestingUserId) {
    private boolean updateSystemSetting(String name, String value, int requestingUserId) {
        if (DEBUG) {
            Slog.v(LOG_TAG, "updateSystemSettingLocked(" + name + ", " + value + ", "
            Slog.v(LOG_TAG, "updateSystemSetting(" + name + ", " + value + ", "
                    + requestingUserId + ")");
        }

        return mutateSystemSettingLocked(name, value, requestingUserId, MUTATION_OPERATION_UPDATE);
        return mutateSystemSetting(name, value, requestingUserId, MUTATION_OPERATION_UPDATE);
    }

    private boolean mutateSystemSettingLocked(String name, String value, int runAsUserId,
    private boolean mutateSystemSetting(String name, String value, int runAsUserId,
            int operation) {
        // Make sure the caller can change the settings.
        enforceWritePermission(Manifest.permission.WRITE_SETTINGS);
@@ -904,10 +920,12 @@ public class SettingsProvider extends ContentProvider {
        }

        // Mutate the value.
        synchronized (mLock) {
            switch (operation) {
                case MUTATION_OPERATION_INSERT: {
                    validateSystemSettingValue(name, value);
                return mSettingsRegistry.insertSettingLocked(SettingsRegistry.SETTINGS_TYPE_SYSTEM,
                    return mSettingsRegistry
                            .insertSettingLocked(SettingsRegistry.SETTINGS_TYPE_SYSTEM,
                                    owningUserId, name, value, getCallingPackage());
                }

@@ -919,13 +937,15 @@ public class SettingsProvider extends ContentProvider {

                case MUTATION_OPERATION_UPDATE: {
                    validateSystemSettingValue(name, value);
                return mSettingsRegistry.updateSettingLocked(SettingsRegistry.SETTINGS_TYPE_SYSTEM,
                    return mSettingsRegistry
                            .updateSettingLocked(SettingsRegistry.SETTINGS_TYPE_SYSTEM,
                                    owningUserId, name, value, getCallingPackage());
                }
            }

            return false;
        }
    }

    private void validateSystemSettingValue(String name, String value) {
        Settings.System.Validator validator = Settings.System.VALIDATORS.get(name);
@@ -1043,6 +1063,7 @@ public class SettingsProvider extends ContentProvider {
        // user info is a cached instance, so just look up instead of cache.
        final long identity = Binder.clearCallingIdentity();
        try {
            // Just a lookup and not reentrant, so holding a lock is fine.
            UserInfo userInfo = mUserManager.getProfileParent(userId);
            return (userInfo != null) ? userInfo.id : userId;
        } finally {
@@ -1088,7 +1109,7 @@ public class SettingsProvider extends ContentProvider {
        // skip prefix
        value = value.substring(1);

        Setting settingValue = getSecureSettingLocked(
        Setting settingValue = getSecureSetting(
                Settings.Secure.LOCATION_PROVIDERS_ALLOWED, owningUserId);

        String oldProviders = (settingValue != null) ? settingValue.getValue() : "";