Home | History | Annotate | Download | only in vehiclemonitor
      1 /*
      2  * Copyright (C) 2016 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 package com.android.car.vehiclemonitor;
     17 
     18 import android.annotation.IntDef;
     19 import android.os.Handler;
     20 import android.os.Looper;
     21 import android.os.Message;
     22 import android.os.RemoteException;
     23 import android.os.ServiceManager;
     24 import android.os.ServiceSpecificException;
     25 
     26 import java.lang.annotation.Retention;
     27 import java.lang.annotation.RetentionPolicy;
     28 import java.lang.ref.WeakReference;
     29 
     30 /**
     31  * System API to access Vehicle monitor. This is only for system services and applications should
     32  * not use this. All APIs will fail with security error if normal app tries this.
     33  */
     34 public class VehicleMonitor {
     35     private static final String TAG = VehicleMonitor.class.getSimpleName();
     36 
     37     private final IVehicleMonitor mService;
     38     private final VehicleMonitorListener mListener;
     39     private final IVehicleMonitorListenerImpl mVehicleMonitorListener;
     40     private final EventHandler mEventHandler;
     41 
     42     private static final int VMS_CONNECT_MAX_RETRY = 10;
     43     private static final long VMS_RETRY_WAIT_TIME_MS = 1000;
     44 
     45     /**
     46      * Application priorities used in vehicle monitoring.
     47      */
     48     @Retention(RetentionPolicy.SOURCE)
     49     @IntDef({
     50             ApplicationPriority.NONE,
     51             ApplicationPriority.FOREGROUND
     52     })
     53     public @interface ApplicationPriority {
     54         int NONE = 0;
     55         int FOREGROUND = 1;
     56     }
     57 
     58     /**
     59      * Listener for VMS events.
     60      */
     61     public interface VehicleMonitorListener {
     62         void onAppViolation(int pid, int uid, int action, int violation);
     63     }
     64 
     65     /**
     66      * Factory method to create VehicleMonitor
     67      */
     68     public static VehicleMonitor createVehicleMonitor(
     69             VehicleMonitorListener listener, Looper looper) {
     70         int retryCount = 0;
     71         IVehicleMonitor service = null;
     72         while (true) {
     73             service = IVehicleMonitor.Stub.asInterface(
     74                     ServiceManager.getService(IVehicleMonitor.class.getCanonicalName()));
     75             if (service != null) {
     76                 break;
     77             }
     78             retryCount++;
     79             if (retryCount > VMS_CONNECT_MAX_RETRY) {
     80                 break;
     81             }
     82             try {
     83                 Thread.sleep(VMS_RETRY_WAIT_TIME_MS);
     84             } catch (InterruptedException e) {
     85                 //ignore
     86             }
     87         }
     88         if (service == null) {
     89             throw new RuntimeException("Vehicle monitor service not available:"
     90                     + IVehicleMonitor.class.getCanonicalName());
     91         }
     92         return new VehicleMonitor(service, listener, looper);
     93     }
     94 
     95     private VehicleMonitor(
     96             IVehicleMonitor service, VehicleMonitorListener listener, Looper looper) {
     97         mService = service;
     98         mListener = listener;
     99         mEventHandler = new EventHandler(looper);
    100         mVehicleMonitorListener = new IVehicleMonitorListenerImpl(this);
    101         try {
    102             mService.setMonitorListener(mVehicleMonitorListener);
    103         } catch (RemoteException e) {
    104             throw new RuntimeException("Vehicle monitor service not working ", e);
    105         }
    106     }
    107 
    108     /**
    109      * Set application priority.
    110      * <p>
    111      * This will lead into writing application priority into vehicle monitor.
    112      */
    113     public void setAppPriority(int pid, int uid, @ApplicationPriority int priority)
    114             throws ServiceSpecificException {
    115         try {
    116             mService.setAppPriority(pid, uid, priority);
    117         } catch (RemoteException e) {
    118             throw new RuntimeException("Vehicle monitor service not working ", e);
    119         }
    120     }
    121 
    122     private void handleVehicleMonitorAppViolation(AppViolation appViolation) {
    123         mListener.onAppViolation(appViolation.mPid, appViolation.mUid, appViolation.mAction,
    124                 appViolation.mViolation);
    125     }
    126 
    127     private class EventHandler extends Handler {
    128 
    129         private static final int MSG_APP_VIOLATION = 0;
    130 
    131         private EventHandler(Looper looper) {
    132             super(looper);
    133         }
    134 
    135         private void notifyAppViolation(int pid, int uid, int action, int violation) {
    136             AppViolation appViolation = new AppViolation(pid, uid, action, violation);
    137             Message msg = obtainMessage(MSG_APP_VIOLATION, appViolation);
    138             sendMessage(msg);
    139         }
    140 
    141         @Override
    142         public void handleMessage(Message msg) {
    143             switch (msg.what) {
    144                 case MSG_APP_VIOLATION:
    145                     AppViolation appViolation = (AppViolation) msg.obj;
    146                     handleVehicleMonitorAppViolation(appViolation);
    147                     break;
    148             }
    149         }
    150     }
    151 
    152     private static class IVehicleMonitorListenerImpl extends IVehicleMonitorListener.Stub {
    153 
    154         private final WeakReference<VehicleMonitor> mVehicleMonitor;
    155 
    156         private IVehicleMonitorListenerImpl(VehicleMonitor vehicleNewotk) {
    157             mVehicleMonitor = new WeakReference<>(vehicleNewotk);
    158         }
    159 
    160         @Override
    161         public void onAppViolation(int pid, int uid, int action, int violation) {
    162             VehicleMonitor vehicleMonitor = mVehicleMonitor.get();
    163             if (vehicleMonitor != null) {
    164                 vehicleMonitor.mEventHandler.notifyAppViolation(pid, uid, action, violation);
    165             }
    166         }
    167     }
    168 
    169     private static class AppViolation {
    170         public final int mPid;
    171         public final int mUid;
    172         public final int mAction;
    173         public final int mViolation;
    174 
    175         AppViolation(int pid, int uid, int action, int violation) {
    176             mPid = pid;
    177             mUid = uid;
    178             mAction = action;
    179             mViolation = violation;
    180         }
    181     }
    182 }
    183