/*
 * Copyright 2021 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 androidx.car.app.hardware;

import static androidx.annotation.RestrictTo.Scope.LIBRARY;

import android.content.Context;

import androidx.annotation.MainThread;
import androidx.annotation.NonNull;
import androidx.annotation.RestrictTo;
import androidx.car.app.HostDispatcher;
import androidx.car.app.annotations.RequiresCarApi;
import androidx.car.app.hardware.info.CarInfo;
import androidx.car.app.hardware.info.CarSensors;
import androidx.car.app.managers.Manager;

/**
 * Manages access to car hardware specific properties and sensors.
 */
@RequiresCarApi(3)
@MainThread
public interface CarHardwareManager extends Manager {
    /**
     * Returns the {@link CarInfo} that can be used to query the car hardware information
     * such as make, model, etc.
     */
    default @NonNull CarInfo getCarInfo() {
        throw new UnsupportedOperationException();
    }

    /**
     * Returns the {@link CarSensors} that can be used to access sensor information from the
     * car hardware.
     */
    default @NonNull CarSensors getCarSensors() {
        throw new UnsupportedOperationException();
    }

    /**
     * Returns an instance of {@link CarHardwareManager} depending on linked library including an
     * optional {@link HostDispatcher}.
     *
     * @throws IllegalStateException if none of the supported classes are found or if a supported
     *                               class was found but the constructor was mismatched
     * @hide
     */
    @RestrictTo(LIBRARY)
    @NonNull
    static CarHardwareManager create(@NonNull Context context,
            @NonNull HostDispatcher hostDispatcher) throws IllegalStateException {
        CarHardwareManager manager = Manager.create(CarHardwareManager.class,
                "androidx.car.app.hardware.AutomotiveCarHardwareManager", context);

        if (manager == null) {
            manager = Manager.create(CarHardwareManager.class,
                    "androidx.car.app.hardware.ProjectedCarHardwareManager", hostDispatcher);
        }

        if (manager == null) {
            throw new IllegalStateException("Unable to instantiate " + CarHardwareManager.class
                    + ". Did you forget to add a dependency on app-automotive or app-projected "
                    + "artifacts?");
        }

        return manager;
    }
}

@@ -853,16 +853,52 @@
 rictTo;%0A
+import androidx.car.app.CarContext;%0A
 import a
@@ -1121,16 +1121,55 @@
 nager;%0A%0A
+import java.lang.reflect.Constructor;%0A%0A
 /**%0A * M
@@ -2243,16 +2243,19 @@
 NonNull 
+Car
 Context 
@@ -2358,256 +2358,704 @@
     
-CarHardwareManager manager = Manager.create(CarHardwareManager.class,%0A                %22androidx.car.app.hardware.AutomotiveCarHardwareManager%22, context);%0A%0A        if (manager == null) %7B%0A            manager = Manager.create(CarHardwareManager.class,
+// TODO(b/192493839) : Switch to using Manager.create%0A        try %7B // Check for automotive library first.%0A            Class%3C?%3E c = Class.forName(%22androidx.car.app.hardware.AutomotiveCarHardwareManager%22);%0A            Constructor%3C?%3E ctor = c.getConstructor(Context.class);%0A            Object object = ctor.newInstance(context);%0A            return (CarHardwareManager) object;%0A        %7D catch (ClassNotFoundException e) %7B%0A            // No Automotive. Fall through.%0A        %7D catch (ReflectiveOperationException e) %7B%0A            // Something went wrong with accessing the constructor or calling newInstance().%0A            throw new IllegalStateException(%22Mismatch with app-automotive artifact%22, e);
 %0A   
@@ -3055,32 +3055,35 @@
 e);%0A        
+%7D%0A%0A
         
     %22android
@@ -3074,228 +3074,728 @@
     
-    %22androidx.car.app.hardware.ProjectedCarHardwareManager%22, hostDispatcher);%0A        %7D%0A%0A        if (manager == null) %7B%0A            throw new IllegalStateException(%22Unable to instantiate %22 + CarHardwareManager.class%0A    
+try %7B // Check for automotive library first.%0A            Class%3C?%3E c = Class.forName(%22androidx.car.app.hardware.ProjectedCarHardwareManager%22);%0A            Constructor%3C?%3E ctor = c.getConstructor(HostDispatcher.class);%0A            Object object = ctor.newInstance(hostDispatcher);%0A            return (CarHardwareManager) object;%0A        %7D catch (ClassNotFoundException e) %7B%0A            // No Projected. Fall through.%0A        %7D catch (ReflectiveOperationException e) %7B%0A            // Something went wrong with accessing the constructor or calling newInstance().%0A            throw new IllegalStateException(%22Mismatch with app-projected artifact%22, e);%0A        %7D%0A%0A        throw new IllegalStateException(%22Vehicle Manager not %22%0A
     
@@ -3809,16 +3809,26 @@
      + %22
+configured
 . Did yo
@@ -3877,30 +3877,16 @@
 tive or 
-app-projected 
 %22%0A      
@@ -3899,62 +3899,37 @@
     
- 
-   
 + %22a
-rtifacts?%22);%0A        %7D%0A%0A        return manager
+pp-projected artifacts?%22)
 ;%0A  

Fix CarHardware.create.