blob: e5c7fc905154ede685bc3956ba5232b92c944b5a [file] [log] [blame]
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.car.ui.utils;
import static android.car.drivingstate.CarUxRestrictions.UX_RESTRICTIONS_LIMIT_STRING_LENGTH;
import android.car.Car;
import android.car.drivingstate.CarUxRestrictions;
import android.car.drivingstate.CarUxRestrictions.CarUxRestrictionsInfo;
import android.car.drivingstate.CarUxRestrictionsManager;
import android.content.Context;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import com.android.car.ui.R;
import java.util.Collections;
import java.util.Set;
import java.util.WeakHashMap;
// This can't be in the middle of the rest of the imports on gerrit or it will
// fail our style checks
// copybara:insert import android.car.CarNotConnectedException;
/**
* Utility class to access Car Restriction Manager.
*
* <p>This class must be a singleton because only one listener can be registered with {@link
* CarUxRestrictionsManager} at a time, as documented in {@link
* CarUxRestrictionsManager#registerListener}.
*/
public class CarUxRestrictionsUtil {
private static final String TAG = "CarUxRestrictionsUtil";
/* copybara:insert
private final Car mCarApi;
private CarUxRestrictionsManager mCarUxRestrictionsManager;
*/
@NonNull
private CarUxRestrictions mCarUxRestrictions = getDefaultRestrictions();
private final Set<OnUxRestrictionsChangedListener> mObservers =
Collections.newSetFromMap(new WeakHashMap<>());
private static CarUxRestrictionsUtil sInstance = null;
private CarUxRestrictionsUtil(Context context) {
CarUxRestrictionsManager.OnUxRestrictionsChangedListener listener =
(carUxRestrictions) -> {
if (carUxRestrictions == null) {
mCarUxRestrictions = getDefaultRestrictions();
} else {
mCarUxRestrictions = carUxRestrictions;
}
for (OnUxRestrictionsChangedListener observer : mObservers) {
observer.onRestrictionsChanged(mCarUxRestrictions);
}
};
// copybara:strip_begin
Car.createCar(context.getApplicationContext(), null, Car.CAR_WAIT_TIMEOUT_DO_NOT_WAIT,
(Car car, boolean ready) -> {
if (ready) {
CarUxRestrictionsManager carUxRestrictionsManager =
(CarUxRestrictionsManager) car.getCarManager(
Car.CAR_UX_RESTRICTION_SERVICE);
carUxRestrictionsManager.registerListener(listener);
listener.onUxRestrictionsChanged(
carUxRestrictionsManager.getCurrentCarUxRestrictions());
} else {
Log.w(TAG, "Car service disconnected, assuming fully restricted uxr");
listener.onUxRestrictionsChanged(null);
}
});
/* copybara:strip_end_and_replace
mCarApi = Car.createCar(context.getApplicationContext());
try {
mCarUxRestrictionsManager =
(CarUxRestrictionsManager) mCarApi.getCarManager(
Car.CAR_UX_RESTRICTION_SERVICE);
mCarUxRestrictionsManager.registerListener(listener);
listener.onUxRestrictionsChanged(
mCarUxRestrictionsManager.getCurrentCarUxRestrictions());
} catch (CarNotConnectedException | NullPointerException e) {
Log.e(TAG, "Car not connected", e);
// mCarUxRestrictions will be the default
}
*/
}
@NonNull
private static CarUxRestrictions getDefaultRestrictions() {
return new CarUxRestrictions.Builder(
true, CarUxRestrictions.UX_RESTRICTIONS_FULLY_RESTRICTED, 0)
.build();
}
/** Listener interface used to update clients on UxRestrictions changes */
public interface OnUxRestrictionsChangedListener {
/** Called when CarUxRestrictions changes */
void onRestrictionsChanged(@NonNull CarUxRestrictions carUxRestrictions);
}
/** Returns the singleton sInstance of this class */
@NonNull
public static CarUxRestrictionsUtil getInstance(Context context) {
if (sInstance == null) {
sInstance = new CarUxRestrictionsUtil(context);
}
return sInstance;
}
/**
* Registers a listener on this class for updates to CarUxRestrictions. Multiple listeners may
* be registered. Note that this class will only hold a weak reference to the listener, you
* must maintain a strong reference to it elsewhere.
*/
public void register(OnUxRestrictionsChangedListener listener) {
mObservers.add(listener);
listener.onRestrictionsChanged(mCarUxRestrictions);
}
/** Unregisters a registered listener */
public void unregister(OnUxRestrictionsChangedListener listener) {
mObservers.remove(listener);
}
@NonNull
public CarUxRestrictions getCurrentRestrictions() {
return mCarUxRestrictions;
}
/**
* Returns whether any of the given flags are blocked by the specified restrictions. If null is
* given, the method returns true for safety.
*/
public static boolean isRestricted(
@CarUxRestrictionsInfo int restrictionFlags, @Nullable CarUxRestrictions uxr) {
return (uxr == null) || ((uxr.getActiveRestrictions() & restrictionFlags) != 0);
}
/**
* Complies the input string with the given UX restrictions. Returns the original string if
* already compliant, otherwise a shortened ellipsized string.
*/
public static String complyString(Context context, String str, CarUxRestrictions uxr) {
if (isRestricted(UX_RESTRICTIONS_LIMIT_STRING_LENGTH, uxr)) {
int maxLength =
uxr == null
? context.getResources().getInteger(
R.integer.car_ui_default_max_string_length)
: uxr.getMaxRestrictedStringLength();
if (str.length() > maxLength) {
return str.substring(0, maxLength) + context.getString(R.string.car_ui_ellipsis);
}
}
return str;
}
/** Sets car UX restrictions. Only used for testing. */
@VisibleForTesting
public void setUxRestrictions(CarUxRestrictions carUxRestrictions) {
mCarUxRestrictions = carUxRestrictions;
}
}