1901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv/*
2901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv * Copyright (C) 2016 The Android Open Source Project
3901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv *
4901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv * Licensed under the Apache License, Version 2.0 (the "License");
5901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv * you may not use this file except in compliance with the License.
6901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv * You may obtain a copy of the License at
7901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv *
8901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv *      http://www.apache.org/licenses/LICENSE-2.0
9901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv *
10901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv * Unless required by applicable law or agreed to in writing, software
11901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv * distributed under the License is distributed on an "AS IS" BASIS,
12901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv * See the License for the specific language governing permissions and
14901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv * limitations under the License.
15901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv */
16901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkivpackage com.android.car.vehiclemonitor;
17901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv
18901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkivimport android.annotation.IntDef;
19901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkivimport android.os.Handler;
20901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkivimport android.os.Looper;
21901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkivimport android.os.Message;
22901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkivimport android.os.RemoteException;
23901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkivimport android.os.ServiceManager;
24901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkivimport android.os.ServiceSpecificException;
25901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv
26901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkivimport java.lang.annotation.Retention;
27901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkivimport java.lang.annotation.RetentionPolicy;
28901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkivimport java.lang.ref.WeakReference;
29901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv
30901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv/**
31901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv * System API to access Vehicle monitor. This is only for system services and applications should
32901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv * not use this. All APIs will fail with security error if normal app tries this.
33901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv */
34901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkivpublic class VehicleMonitor {
35901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv    private static final String TAG = VehicleMonitor.class.getSimpleName();
36901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv
37901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv    private final IVehicleMonitor mService;
38901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv    private final VehicleMonitorListener mListener;
39901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv    private final IVehicleMonitorListenerImpl mVehicleMonitorListener;
40901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv    private final EventHandler mEventHandler;
41901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv
42901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv    private static final int VMS_CONNECT_MAX_RETRY = 10;
43901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv    private static final long VMS_RETRY_WAIT_TIME_MS = 1000;
44901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv
45901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv    /**
46901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv     * Application priorities used in vehicle monitoring.
47901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv     */
48901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv    @Retention(RetentionPolicy.SOURCE)
49901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv    @IntDef({
50901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv            ApplicationPriority.NONE,
51901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv            ApplicationPriority.FOREGROUND
52901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv    })
53901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv    public @interface ApplicationPriority {
54901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv        int NONE = 0;
55901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv        int FOREGROUND = 1;
56901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv    }
57901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv
58901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv    /**
59901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv     * Listener for VMS events.
60901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv     */
61901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv    public interface VehicleMonitorListener {
62901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv        void onAppViolation(int pid, int uid, int action, int violation);
63901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv    }
64901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv
65901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv    /**
66901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv     * Factory method to create VehicleMonitor
67901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv     */
68901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv    public static VehicleMonitor createVehicleMonitor(
69901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv            VehicleMonitorListener listener, Looper looper) {
70901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv        int retryCount = 0;
71901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv        IVehicleMonitor service = null;
72901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv        while (true) {
73901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv            service = IVehicleMonitor.Stub.asInterface(
74901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv                    ServiceManager.getService(IVehicleMonitor.class.getCanonicalName()));
75901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv            if (service != null) {
76901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv                break;
77901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv            }
78901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv            retryCount++;
79901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv            if (retryCount > VMS_CONNECT_MAX_RETRY) {
80901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv                break;
81901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv            }
82901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv            try {
83901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv                Thread.sleep(VMS_RETRY_WAIT_TIME_MS);
84901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv            } catch (InterruptedException e) {
85901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv                //ignore
86901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv            }
87901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv        }
88901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv        if (service == null) {
89901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv            throw new RuntimeException("Vehicle monitor service not available:"
90901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv                    + IVehicleMonitor.class.getCanonicalName());
91901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv        }
92901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv        return new VehicleMonitor(service, listener, looper);
93901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv    }
94901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv
95901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv    private VehicleMonitor(
96901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv            IVehicleMonitor service, VehicleMonitorListener listener, Looper looper) {
97901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv        mService = service;
98901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv        mListener = listener;
99901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv        mEventHandler = new EventHandler(looper);
100901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv        mVehicleMonitorListener = new IVehicleMonitorListenerImpl(this);
101901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv        try {
102901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv            mService.setMonitorListener(mVehicleMonitorListener);
103901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv        } catch (RemoteException e) {
104901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv            throw new RuntimeException("Vehicle monitor service not working ", e);
105901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv        }
106901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv    }
107901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv
108901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv    /**
109901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv     * Set application priority.
110901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv     * <p>
111901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv     * This will lead into writing application priority into vehicle monitor.
112901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv     */
113901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv    public void setAppPriority(int pid, int uid, @ApplicationPriority int priority)
114901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv            throws ServiceSpecificException {
115901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv        try {
116901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv            mService.setAppPriority(pid, uid, priority);
117901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv        } catch (RemoteException e) {
118901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv            throw new RuntimeException("Vehicle monitor service not working ", e);
119901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv        }
120901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv    }
121901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv
122901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv    private void handleVehicleMonitorAppViolation(AppViolation appViolation) {
123901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv        mListener.onAppViolation(appViolation.mPid, appViolation.mUid, appViolation.mAction,
124901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv                appViolation.mViolation);
125901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv    }
126901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv
127901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv    private class EventHandler extends Handler {
128901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv
129901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv        private static final int MSG_APP_VIOLATION = 0;
130901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv
131901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv        private EventHandler(Looper looper) {
132901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv            super(looper);
133901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv        }
134901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv
135901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv        private void notifyAppViolation(int pid, int uid, int action, int violation) {
136901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv            AppViolation appViolation = new AppViolation(pid, uid, action, violation);
137901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv            Message msg = obtainMessage(MSG_APP_VIOLATION, appViolation);
138901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv            sendMessage(msg);
139901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv        }
140901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv
141901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv        @Override
142901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv        public void handleMessage(Message msg) {
143901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv            switch (msg.what) {
144901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv                case MSG_APP_VIOLATION:
145901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv                    AppViolation appViolation = (AppViolation) msg.obj;
146901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv                    handleVehicleMonitorAppViolation(appViolation);
147901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv                    break;
148901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv            }
149901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv        }
150901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv    }
151901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv
152901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv    private static class IVehicleMonitorListenerImpl extends IVehicleMonitorListener.Stub {
153901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv
154901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv        private final WeakReference<VehicleMonitor> mVehicleMonitor;
155901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv
156901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv        private IVehicleMonitorListenerImpl(VehicleMonitor vehicleNewotk) {
157901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv            mVehicleMonitor = new WeakReference<>(vehicleNewotk);
158901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv        }
159901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv
160901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv        @Override
161901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv        public void onAppViolation(int pid, int uid, int action, int violation) {
162901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv            VehicleMonitor vehicleMonitor = mVehicleMonitor.get();
163901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv            if (vehicleMonitor != null) {
164901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv                vehicleMonitor.mEventHandler.notifyAppViolation(pid, uid, action, violation);
165901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv            }
166901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv        }
167901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv    }
168901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv
169901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv    private static class AppViolation {
170901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv        public final int mPid;
171901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv        public final int mUid;
172901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv        public final int mAction;
173901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv        public final int mViolation;
174901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv
175901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv        AppViolation(int pid, int uid, int action, int violation) {
176901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv            mPid = pid;
177901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv            mUid = uid;
178901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv            mAction = action;
179901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv            mViolation = violation;
180901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv        }
181901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv    }
182901c024b7d764a1e1556e99ffcd3da8522c8a0b8Vitalii Tomkiv}
183