// Code generated by protoc-gen-go. DO NOT EDIT.
// source: device_minimum_version_service.proto

package policy

import (
	context "context"
	fmt "fmt"
	proto "github.com/golang/protobuf/proto"
	empty "github.com/golang/protobuf/ptypes/empty"
	grpc "google.golang.org/grpc"
	codes "google.golang.org/grpc/codes"
	status "google.golang.org/grpc/status"
	math "math"
)

// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf

// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package

func init() {
	proto.RegisterFile("device_minimum_version_service.proto", fileDescriptor_9a09e348d375da07)
}

var fileDescriptor_9a09e348d375da07 = []byte{
	// 198 bytes of a gzipped FileDescriptorProto
	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x8f, 0xb1, 0x6e, 0x83, 0x30,
	0x10, 0x86, 0x3b, 0x75, 0x60, 0xaa, 0x18, 0x3a, 0xc0, 0xd4, 0x0a, 0x75, 0xb4, 0xa5, 0xe6, 0x0d,
	0xa2, 0x64, 0xc8, 0x90, 0x25, 0x04, 0x86, 0x2c, 0x08, 0xcc, 0x85, 0x9c, 0x84, 0x39, 0xc7, 0x67,
	0x23, 0xf1, 0xf6, 0x91, 0x71, 0x32, 0x66, 0xfd, 0xef, 0xee, 0xfb, 0xbf, 0x4b, 0x8a, 0x1e, 0x66,
	0x54, 0xd0, 0x68, 0x9c, 0x50, 0x7b, 0xdd, 0xcc, 0x60, 0x19, 0x69, 0x6a, 0x18, 0x6c, 0xc8, 0x85,
	0xb1, 0xe4, 0x28, 0xfd, 0x72, 0x2d, 0x3b, 0xa1, 0x2c, 0xb1, 0x30, 0x34, 0xa2, 0x5a, 0xb2, 0x7c,
	0x20, 0x1a, 0x46, 0x90, 0xeb, 0xbc, 0xf3, 0x57, 0x09, 0xda, 0xb8, 0x25, 0xae, 0xff, 0xbb, 0x24,
	0xdf, 0xad, 0xd8, 0x63, 0xa4, 0xd6, 0x11, 0x5a, 0x46, 0x66, 0x5a, 0x25, 0x3f, 0x67, 0x60, 0x57,
	0x99, 0xbe, 0x75, 0x70, 0x82, 0xbb, 0x47, 0x0b, 0x7d, 0xa9, 0x2c, 0xc0, 0x74, 0xe0, 0x1a, 0x19,
	0xbb, 0x11, 0xd2, 0x6f, 0x11, 0x1b, 0xc4, 0xab, 0x41, 0xec, 0x43, 0x43, 0xf6, 0x26, 0xff, 0xfd,
	0xd8, 0xfe, 0x5d, 0x0a, 0x75, 0xb3, 0xa4, 0xd1, 0x6b, 0x62, 0x19, 0x8c, 0xe5, 0xf3, 0x0b, 0x96,
	0x41, 0x5d, 0x46, 0xf5, 0xee, 0x73, 0xbd, 0xdc, 0x3c, 0x02, 0x00, 0x00, 0xff, 0xff, 0xfe, 0x34,
	0x74, 0x68, 0xfb, 0x00, 0x00, 0x00,
}

// Reference imports to suppress errors if they are not otherwise used.
var _ context.Context
var _ grpc.ClientConn

// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
const _ = grpc.SupportPackageIsVersion4

// DeviceMinimumVersionServiceClient is the client API for DeviceMinimumVersionService service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
type DeviceMinimumVersionServiceClient interface {
	// Creates a new instance of Chrome using the state from the existing one.
	// Checks that an update required screen with update now button is visible on the login page.
	// Chrome is closed when function exists. This is used by the test policy.DeviceMinimumVersion.
	TestUpdateRequiredScreenIsVisible(ctx context.Context, in *empty.Empty, opts ...grpc.CallOption) (*empty.Empty, error)
}

type deviceMinimumVersionServiceClient struct {
	cc *grpc.ClientConn
}

func NewDeviceMinimumVersionServiceClient(cc *grpc.ClientConn) DeviceMinimumVersionServiceClient {
	return &deviceMinimumVersionServiceClient{cc}
}

func (c *deviceMinimumVersionServiceClient) TestUpdateRequiredScreenIsVisible(ctx context.Context, in *empty.Empty, opts ...grpc.CallOption) (*empty.Empty, error) {
	out := new(empty.Empty)
	err := c.cc.Invoke(ctx, "/tast.cros.policy.DeviceMinimumVersionService/TestUpdateRequiredScreenIsVisible", in, out, opts...)
	if err != nil {
		return nil, err
	}
	return out, nil
}

// DeviceMinimumVersionServiceServer is the server API for DeviceMinimumVersionService service.
type DeviceMinimumVersionServiceServer interface {
	// Creates a new instance of Chrome using the state from the existing one.
	// Checks that an update required screen with update now button is visible on the login page.
	// Chrome is closed when function exists. This is used by the test policy.DeviceMinimumVersion.
	TestUpdateRequiredScreenIsVisible(context.Context, *empty.Empty) (*empty.Empty, error)
}

// UnimplementedDeviceMinimumVersionServiceServer can be embedded to have forward compatible implementations.
type UnimplementedDeviceMinimumVersionServiceServer struct {
}

func (*UnimplementedDeviceMinimumVersionServiceServer) TestUpdateRequiredScreenIsVisible(ctx context.Context, req *empty.Empty) (*empty.Empty, error) {
	return nil, status.Errorf(codes.Unimplemented, "method TestUpdateRequiredScreenIsVisible not implemented")
}

func RegisterDeviceMinimumVersionServiceServer(s *grpc.Server, srv DeviceMinimumVersionServiceServer) {
	s.RegisterService(&_DeviceMinimumVersionService_serviceDesc, srv)
}

func _DeviceMinimumVersionService_TestUpdateRequiredScreenIsVisible_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
	in := new(empty.Empty)
	if err := dec(in); err != nil {
		return nil, err
	}
	if interceptor == nil {
		return srv.(DeviceMinimumVersionServiceServer).TestUpdateRequiredScreenIsVisible(ctx, in)
	}
	info := &grpc.UnaryServerInfo{
		Server:     srv,
		FullMethod: "/tast.cros.policy.DeviceMinimumVersionService/TestUpdateRequiredScreenIsVisible",
	}
	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
		return srv.(DeviceMinimumVersionServiceServer).TestUpdateRequiredScreenIsVisible(ctx, req.(*empty.Empty))
	}
	return interceptor(ctx, in, info, handler)
}

var _DeviceMinimumVersionService_serviceDesc = grpc.ServiceDesc{
	ServiceName: "tast.cros.policy.DeviceMinimumVersionService",
	HandlerType: (*DeviceMinimumVersionServiceServer)(nil),
	Methods: []grpc.MethodDesc{
		{
			MethodName: "TestUpdateRequiredScreenIsVisible",
			Handler:    _DeviceMinimumVersionService_TestUpdateRequiredScreenIsVisible_Handler,
		},
	},
	Streams:  []grpc.StreamDesc{},
	Metadata: "device_minimum_version_service.proto",
}
