Home | History | Annotate | Download | only in app
      1 /*
      2  * Copyright (C) 2012 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 
     17 package android.app;
     18 
     19 import android.os.Binder;
     20 import android.os.IBinder;
     21 import android.util.ArrayMap;
     22 import com.android.internal.app.IAppOpsService;
     23 import com.android.internal.app.IAppOpsCallback;
     24 
     25 import java.util.ArrayList;
     26 import java.util.HashMap;
     27 import java.util.List;
     28 
     29 import android.content.Context;
     30 import android.os.Parcel;
     31 import android.os.Parcelable;
     32 import android.os.Process;
     33 import android.os.RemoteException;
     34 
     35 /**
     36  * API for interacting with "application operation" tracking.
     37  *
     38  * <p>This API is not generally intended for third party application developers; most
     39  * features are only available to system applicatins.  Obtain an instance of it through
     40  * {@link Context#getSystemService(String) Context.getSystemService} with
     41  * {@link Context#APP_OPS_SERVICE Context.APP_OPS_SERVICE}.</p>
     42  */
     43 public class AppOpsManager {
     44     /**
     45      * <p>App ops allows callers to:</p>
     46      *
     47      * <ul>
     48      * <li> Note when operations are happening, and find out if they are allowed for the current
     49      * caller.</li>
     50      * <li> Disallow specific apps from doing specific operations.</li>
     51      * <li> Collect all of the current information about operations that have been executed or
     52      * are not being allowed.</li>
     53      * <li> Monitor for changes in whether an operation is allowed.</li>
     54      * </ul>
     55      *
     56      * <p>Each operation is identified by a single integer; these integers are a fixed set of
     57      * operations, enumerated by the OP_* constants.
     58      *
     59      * <p></p>When checking operations, the result is a "mode" integer indicating the current
     60      * setting for the operation under that caller: MODE_ALLOWED, MODE_IGNORED (don't execute
     61      * the operation but fake its behavior enough so that the caller doesn't crash),
     62      * MODE_ERRORED (throw a SecurityException back to the caller; the normal operation calls
     63      * will do this for you).
     64      */
     65 
     66     final Context mContext;
     67     final IAppOpsService mService;
     68     final ArrayMap<OnOpChangedListener, IAppOpsCallback> mModeWatchers
     69             = new ArrayMap<OnOpChangedListener, IAppOpsCallback>();
     70 
     71     static IBinder sToken;
     72 
     73     /**
     74      * Result from {@link #checkOp}, {@link #noteOp}, {@link #startOp}: the given caller is
     75      * allowed to perform the given operation.
     76      */
     77     public static final int MODE_ALLOWED = 0;
     78 
     79     /**
     80      * Result from {@link #checkOp}, {@link #noteOp}, {@link #startOp}: the given caller is
     81      * not allowed to perform the given operation, and this attempt should
     82      * <em>silently fail</em> (it should not cause the app to crash).
     83      */
     84     public static final int MODE_IGNORED = 1;
     85 
     86     /**
     87      * Result from {@link #checkOpNoThrow}, {@link #noteOpNoThrow}, {@link #startOpNoThrow}: the
     88      * given caller is not allowed to perform the given operation, and this attempt should
     89      * cause it to have a fatal error, typically a {@link SecurityException}.
     90      */
     91     public static final int MODE_ERRORED = 2;
     92 
     93     // when adding one of these:
     94     //  - increment _NUM_OP
     95     //  - add rows to sOpToSwitch, sOpToString, sOpNames, sOpPerms, sOpDefaultMode
     96     //  - add descriptive strings to Settings/res/values/arrays.xml
     97     //  - add the op to the appropriate template in AppOpsState.OpsTemplate (settings app)
     98 
     99     /** @hide No operation specified. */
    100     public static final int OP_NONE = -1;
    101     /** @hide Access to coarse location information. */
    102     public static final int OP_COARSE_LOCATION = 0;
    103     /** @hide Access to fine location information. */
    104     public static final int OP_FINE_LOCATION = 1;
    105     /** @hide Causing GPS to run. */
    106     public static final int OP_GPS = 2;
    107     /** @hide */
    108     public static final int OP_VIBRATE = 3;
    109     /** @hide */
    110     public static final int OP_READ_CONTACTS = 4;
    111     /** @hide */
    112     public static final int OP_WRITE_CONTACTS = 5;
    113     /** @hide */
    114     public static final int OP_READ_CALL_LOG = 6;
    115     /** @hide */
    116     public static final int OP_WRITE_CALL_LOG = 7;
    117     /** @hide */
    118     public static final int OP_READ_CALENDAR = 8;
    119     /** @hide */
    120     public static final int OP_WRITE_CALENDAR = 9;
    121     /** @hide */
    122     public static final int OP_WIFI_SCAN = 10;
    123     /** @hide */
    124     public static final int OP_POST_NOTIFICATION = 11;
    125     /** @hide */
    126     public static final int OP_NEIGHBORING_CELLS = 12;
    127     /** @hide */
    128     public static final int OP_CALL_PHONE = 13;
    129     /** @hide */
    130     public static final int OP_READ_SMS = 14;
    131     /** @hide */
    132     public static final int OP_WRITE_SMS = 15;
    133     /** @hide */
    134     public static final int OP_RECEIVE_SMS = 16;
    135     /** @hide */
    136     public static final int OP_RECEIVE_EMERGECY_SMS = 17;
    137     /** @hide */
    138     public static final int OP_RECEIVE_MMS = 18;
    139     /** @hide */
    140     public static final int OP_RECEIVE_WAP_PUSH = 19;
    141     /** @hide */
    142     public static final int OP_SEND_SMS = 20;
    143     /** @hide */
    144     public static final int OP_READ_ICC_SMS = 21;
    145     /** @hide */
    146     public static final int OP_WRITE_ICC_SMS = 22;
    147     /** @hide */
    148     public static final int OP_WRITE_SETTINGS = 23;
    149     /** @hide */
    150     public static final int OP_SYSTEM_ALERT_WINDOW = 24;
    151     /** @hide */
    152     public static final int OP_ACCESS_NOTIFICATIONS = 25;
    153     /** @hide */
    154     public static final int OP_CAMERA = 26;
    155     /** @hide */
    156     public static final int OP_RECORD_AUDIO = 27;
    157     /** @hide */
    158     public static final int OP_PLAY_AUDIO = 28;
    159     /** @hide */
    160     public static final int OP_READ_CLIPBOARD = 29;
    161     /** @hide */
    162     public static final int OP_WRITE_CLIPBOARD = 30;
    163     /** @hide */
    164     public static final int OP_TAKE_MEDIA_BUTTONS = 31;
    165     /** @hide */
    166     public static final int OP_TAKE_AUDIO_FOCUS = 32;
    167     /** @hide */
    168     public static final int OP_AUDIO_MASTER_VOLUME = 33;
    169     /** @hide */
    170     public static final int OP_AUDIO_VOICE_VOLUME = 34;
    171     /** @hide */
    172     public static final int OP_AUDIO_RING_VOLUME = 35;
    173     /** @hide */
    174     public static final int OP_AUDIO_MEDIA_VOLUME = 36;
    175     /** @hide */
    176     public static final int OP_AUDIO_ALARM_VOLUME = 37;
    177     /** @hide */
    178     public static final int OP_AUDIO_NOTIFICATION_VOLUME = 38;
    179     /** @hide */
    180     public static final int OP_AUDIO_BLUETOOTH_VOLUME = 39;
    181     /** @hide */
    182     public static final int OP_WAKE_LOCK = 40;
    183     /** @hide Continually monitoring location data. */
    184     public static final int OP_MONITOR_LOCATION = 41;
    185     /** @hide Continually monitoring location data with a relatively high power request. */
    186     public static final int OP_MONITOR_HIGH_POWER_LOCATION = 42;
    187     /** @hide */
    188     public static final int _NUM_OP = 43;
    189 
    190     /** Access to coarse location information. */
    191     public static final String OPSTR_COARSE_LOCATION =
    192             "android:coarse_location";
    193     /** Access to fine location information. */
    194     public static final String OPSTR_FINE_LOCATION =
    195             "android:fine_location";
    196     /** Continually monitoring location data. */
    197     public static final String OPSTR_MONITOR_LOCATION
    198             = "android:monitor_location";
    199     /** Continually monitoring location data with a relatively high power request. */
    200     public static final String OPSTR_MONITOR_HIGH_POWER_LOCATION
    201             = "android:monitor_location_high_power";
    202 
    203     /**
    204      * This maps each operation to the operation that serves as the
    205      * switch to determine whether it is allowed.  Generally this is
    206      * a 1:1 mapping, but for some things (like location) that have
    207      * multiple low-level operations being tracked that should be
    208      * presented to the user as one switch then this can be used to
    209      * make them all controlled by the same single operation.
    210      */
    211     private static int[] sOpToSwitch = new int[] {
    212             OP_COARSE_LOCATION,
    213             OP_COARSE_LOCATION,
    214             OP_COARSE_LOCATION,
    215             OP_VIBRATE,
    216             OP_READ_CONTACTS,
    217             OP_WRITE_CONTACTS,
    218             OP_READ_CALL_LOG,
    219             OP_WRITE_CALL_LOG,
    220             OP_READ_CALENDAR,
    221             OP_WRITE_CALENDAR,
    222             OP_COARSE_LOCATION,
    223             OP_POST_NOTIFICATION,
    224             OP_COARSE_LOCATION,
    225             OP_CALL_PHONE,
    226             OP_READ_SMS,
    227             OP_WRITE_SMS,
    228             OP_RECEIVE_SMS,
    229             OP_RECEIVE_SMS,
    230             OP_RECEIVE_SMS,
    231             OP_RECEIVE_SMS,
    232             OP_SEND_SMS,
    233             OP_READ_SMS,
    234             OP_WRITE_SMS,
    235             OP_WRITE_SETTINGS,
    236             OP_SYSTEM_ALERT_WINDOW,
    237             OP_ACCESS_NOTIFICATIONS,
    238             OP_CAMERA,
    239             OP_RECORD_AUDIO,
    240             OP_PLAY_AUDIO,
    241             OP_READ_CLIPBOARD,
    242             OP_WRITE_CLIPBOARD,
    243             OP_TAKE_MEDIA_BUTTONS,
    244             OP_TAKE_AUDIO_FOCUS,
    245             OP_AUDIO_MASTER_VOLUME,
    246             OP_AUDIO_VOICE_VOLUME,
    247             OP_AUDIO_RING_VOLUME,
    248             OP_AUDIO_MEDIA_VOLUME,
    249             OP_AUDIO_ALARM_VOLUME,
    250             OP_AUDIO_NOTIFICATION_VOLUME,
    251             OP_AUDIO_BLUETOOTH_VOLUME,
    252             OP_WAKE_LOCK,
    253             OP_COARSE_LOCATION,
    254             OP_COARSE_LOCATION,
    255     };
    256 
    257     /**
    258      * This maps each operation to the public string constant for it.
    259      * If it doesn't have a public string constant, it maps to null.
    260      */
    261     private static String[] sOpToString = new String[] {
    262             OPSTR_COARSE_LOCATION,
    263             OPSTR_FINE_LOCATION,
    264             null,
    265             null,
    266             null,
    267             null,
    268             null,
    269             null,
    270             null,
    271             null,
    272             null,
    273             null,
    274             null,
    275             null,
    276             null,
    277             null,
    278             null,
    279             null,
    280             null,
    281             null,
    282             null,
    283             null,
    284             null,
    285             null,
    286             null,
    287             null,
    288             null,
    289             null,
    290             null,
    291             null,
    292             null,
    293             null,
    294             null,
    295             null,
    296             null,
    297             null,
    298             null,
    299             null,
    300             null,
    301             null,
    302             null,
    303             OPSTR_MONITOR_LOCATION,
    304             OPSTR_MONITOR_HIGH_POWER_LOCATION,
    305     };
    306 
    307     /**
    308      * This provides a simple name for each operation to be used
    309      * in debug output.
    310      */
    311     private static String[] sOpNames = new String[] {
    312             "COARSE_LOCATION",
    313             "FINE_LOCATION",
    314             "GPS",
    315             "VIBRATE",
    316             "READ_CONTACTS",
    317             "WRITE_CONTACTS",
    318             "READ_CALL_LOG",
    319             "WRITE_CALL_LOG",
    320             "READ_CALENDAR",
    321             "WRITE_CALENDAR",
    322             "WIFI_SCAN",
    323             "POST_NOTIFICATION",
    324             "NEIGHBORING_CELLS",
    325             "CALL_PHONE",
    326             "READ_SMS",
    327             "WRITE_SMS",
    328             "RECEIVE_SMS",
    329             "RECEIVE_EMERGECY_SMS",
    330             "RECEIVE_MMS",
    331             "RECEIVE_WAP_PUSH",
    332             "SEND_SMS",
    333             "READ_ICC_SMS",
    334             "WRITE_ICC_SMS",
    335             "WRITE_SETTINGS",
    336             "SYSTEM_ALERT_WINDOW",
    337             "ACCESS_NOTIFICATIONS",
    338             "CAMERA",
    339             "RECORD_AUDIO",
    340             "PLAY_AUDIO",
    341             "READ_CLIPBOARD",
    342             "WRITE_CLIPBOARD",
    343             "TAKE_MEDIA_BUTTONS",
    344             "TAKE_AUDIO_FOCUS",
    345             "AUDIO_MASTER_VOLUME",
    346             "AUDIO_VOICE_VOLUME",
    347             "AUDIO_RING_VOLUME",
    348             "AUDIO_MEDIA_VOLUME",
    349             "AUDIO_ALARM_VOLUME",
    350             "AUDIO_NOTIFICATION_VOLUME",
    351             "AUDIO_BLUETOOTH_VOLUME",
    352             "WAKE_LOCK",
    353             "MONITOR_LOCATION",
    354             "MONITOR_HIGH_POWER_LOCATION",
    355     };
    356 
    357     /**
    358      * This optionally maps a permission to an operation.  If there
    359      * is no permission associated with an operation, it is null.
    360      */
    361     private static String[] sOpPerms = new String[] {
    362             android.Manifest.permission.ACCESS_COARSE_LOCATION,
    363             android.Manifest.permission.ACCESS_FINE_LOCATION,
    364             null,
    365             android.Manifest.permission.VIBRATE,
    366             android.Manifest.permission.READ_CONTACTS,
    367             android.Manifest.permission.WRITE_CONTACTS,
    368             android.Manifest.permission.READ_CALL_LOG,
    369             android.Manifest.permission.WRITE_CALL_LOG,
    370             android.Manifest.permission.READ_CALENDAR,
    371             android.Manifest.permission.WRITE_CALENDAR,
    372             null, // no permission required for notifications
    373             android.Manifest.permission.ACCESS_WIFI_STATE,
    374             null, // neighboring cells shares the coarse location perm
    375             android.Manifest.permission.CALL_PHONE,
    376             android.Manifest.permission.READ_SMS,
    377             android.Manifest.permission.WRITE_SMS,
    378             android.Manifest.permission.RECEIVE_SMS,
    379             android.Manifest.permission.RECEIVE_EMERGENCY_BROADCAST,
    380             android.Manifest.permission.RECEIVE_MMS,
    381             android.Manifest.permission.RECEIVE_WAP_PUSH,
    382             android.Manifest.permission.SEND_SMS,
    383             android.Manifest.permission.READ_SMS,
    384             android.Manifest.permission.WRITE_SMS,
    385             android.Manifest.permission.WRITE_SETTINGS,
    386             android.Manifest.permission.SYSTEM_ALERT_WINDOW,
    387             android.Manifest.permission.ACCESS_NOTIFICATIONS,
    388             android.Manifest.permission.CAMERA,
    389             android.Manifest.permission.RECORD_AUDIO,
    390             null, // no permission for playing audio
    391             null, // no permission for reading clipboard
    392             null, // no permission for writing clipboard
    393             null, // no permission for taking media buttons
    394             null, // no permission for taking audio focus
    395             null, // no permission for changing master volume
    396             null, // no permission for changing voice volume
    397             null, // no permission for changing ring volume
    398             null, // no permission for changing media volume
    399             null, // no permission for changing alarm volume
    400             null, // no permission for changing notification volume
    401             null, // no permission for changing bluetooth volume
    402             android.Manifest.permission.WAKE_LOCK,
    403             null, // no permission for generic location monitoring
    404             null, // no permission for high power location monitoring
    405     };
    406 
    407     /**
    408      * This specifies the default mode for each operation.
    409      */
    410     private static int[] sOpDefaultMode = new int[] {
    411             AppOpsManager.MODE_ALLOWED,
    412             AppOpsManager.MODE_ALLOWED,
    413             AppOpsManager.MODE_ALLOWED,
    414             AppOpsManager.MODE_ALLOWED,
    415             AppOpsManager.MODE_ALLOWED,
    416             AppOpsManager.MODE_ALLOWED,
    417             AppOpsManager.MODE_ALLOWED,
    418             AppOpsManager.MODE_ALLOWED,
    419             AppOpsManager.MODE_ALLOWED,
    420             AppOpsManager.MODE_ALLOWED,
    421             AppOpsManager.MODE_ALLOWED,
    422             AppOpsManager.MODE_ALLOWED,
    423             AppOpsManager.MODE_ALLOWED,
    424             AppOpsManager.MODE_ALLOWED,
    425             AppOpsManager.MODE_ALLOWED,
    426             AppOpsManager.MODE_IGNORED, // OP_WRITE_SMS
    427             AppOpsManager.MODE_ALLOWED,
    428             AppOpsManager.MODE_ALLOWED,
    429             AppOpsManager.MODE_ALLOWED,
    430             AppOpsManager.MODE_ALLOWED,
    431             AppOpsManager.MODE_ALLOWED,
    432             AppOpsManager.MODE_ALLOWED,
    433             AppOpsManager.MODE_ALLOWED,
    434             AppOpsManager.MODE_ALLOWED,
    435             AppOpsManager.MODE_ALLOWED,
    436             AppOpsManager.MODE_ALLOWED,
    437             AppOpsManager.MODE_ALLOWED,
    438             AppOpsManager.MODE_ALLOWED,
    439             AppOpsManager.MODE_ALLOWED,
    440             AppOpsManager.MODE_ALLOWED,
    441             AppOpsManager.MODE_ALLOWED,
    442             AppOpsManager.MODE_ALLOWED,
    443             AppOpsManager.MODE_ALLOWED,
    444             AppOpsManager.MODE_ALLOWED,
    445             AppOpsManager.MODE_ALLOWED,
    446             AppOpsManager.MODE_ALLOWED,
    447             AppOpsManager.MODE_ALLOWED,
    448             AppOpsManager.MODE_ALLOWED,
    449             AppOpsManager.MODE_ALLOWED,
    450             AppOpsManager.MODE_ALLOWED,
    451             AppOpsManager.MODE_ALLOWED,
    452             AppOpsManager.MODE_ALLOWED,
    453             AppOpsManager.MODE_ALLOWED,
    454     };
    455 
    456     /**
    457      * This specifies whether each option is allowed to be reset
    458      * when resetting all app preferences.  Disable reset for
    459      * app ops that are under strong control of some part of the
    460      * system (such as OP_WRITE_SMS, which should be allowed only
    461      * for whichever app is selected as the current SMS app).
    462      */
    463     private static boolean[] sOpDisableReset = new boolean[] {
    464             false,
    465             false,
    466             false,
    467             false,
    468             false,
    469             false,
    470             false,
    471             false,
    472             false,
    473             false,
    474             false,
    475             false,
    476             false,
    477             false,
    478             false,
    479             true,      // OP_WRITE_SMS
    480             false,
    481             false,
    482             false,
    483             false,
    484             false,
    485             false,
    486             false,
    487             false,
    488             false,
    489             false,
    490             false,
    491             false,
    492             false,
    493             false,
    494             false,
    495             false,
    496             false,
    497             false,
    498             false,
    499             false,
    500             false,
    501             false,
    502             false,
    503             false,
    504             false,
    505             false,
    506             false,
    507     };
    508 
    509     private static HashMap<String, Integer> sOpStrToOp = new HashMap<String, Integer>();
    510 
    511     static {
    512         if (sOpToSwitch.length != _NUM_OP) {
    513             throw new IllegalStateException("sOpToSwitch length " + sOpToSwitch.length
    514                     + " should be " + _NUM_OP);
    515         }
    516         if (sOpToString.length != _NUM_OP) {
    517             throw new IllegalStateException("sOpToString length " + sOpToString.length
    518                     + " should be " + _NUM_OP);
    519         }
    520         if (sOpNames.length != _NUM_OP) {
    521             throw new IllegalStateException("sOpNames length " + sOpNames.length
    522                     + " should be " + _NUM_OP);
    523         }
    524         if (sOpPerms.length != _NUM_OP) {
    525             throw new IllegalStateException("sOpPerms length " + sOpPerms.length
    526                     + " should be " + _NUM_OP);
    527         }
    528         if (sOpDefaultMode.length != _NUM_OP) {
    529             throw new IllegalStateException("sOpDefaultMode length " + sOpDefaultMode.length
    530                     + " should be " + _NUM_OP);
    531         }
    532         if (sOpDisableReset.length != _NUM_OP) {
    533             throw new IllegalStateException("sOpDisableReset length " + sOpDisableReset.length
    534                     + " should be " + _NUM_OP);
    535         }
    536         for (int i=0; i<_NUM_OP; i++) {
    537             if (sOpToString[i] != null) {
    538                 sOpStrToOp.put(sOpToString[i], i);
    539             }
    540         }
    541     }
    542 
    543     /**
    544      * Retrieve the op switch that controls the given operation.
    545      * @hide
    546      */
    547     public static int opToSwitch(int op) {
    548         return sOpToSwitch[op];
    549     }
    550 
    551     /**
    552      * Retrieve a non-localized name for the operation, for debugging output.
    553      * @hide
    554      */
    555     public static String opToName(int op) {
    556         if (op == OP_NONE) return "NONE";
    557         return op < sOpNames.length ? sOpNames[op] : ("Unknown(" + op + ")");
    558     }
    559 
    560     /**
    561      * Retrieve the permission associated with an operation, or null if there is not one.
    562      * @hide
    563      */
    564     public static String opToPermission(int op) {
    565         return sOpPerms[op];
    566     }
    567 
    568     /**
    569      * Retrieve the default mode for the operation.
    570      * @hide
    571      */
    572     public static int opToDefaultMode(int op) {
    573         return sOpDefaultMode[op];
    574     }
    575 
    576     /**
    577      * Retrieve whether the op allows itself to be reset.
    578      * @hide
    579      */
    580     public static boolean opAllowsReset(int op) {
    581         return !sOpDisableReset[op];
    582     }
    583 
    584     /**
    585      * Class holding all of the operation information associated with an app.
    586      * @hide
    587      */
    588     public static class PackageOps implements Parcelable {
    589         private final String mPackageName;
    590         private final int mUid;
    591         private final List<OpEntry> mEntries;
    592 
    593         public PackageOps(String packageName, int uid, List<OpEntry> entries) {
    594             mPackageName = packageName;
    595             mUid = uid;
    596             mEntries = entries;
    597         }
    598 
    599         public String getPackageName() {
    600             return mPackageName;
    601         }
    602 
    603         public int getUid() {
    604             return mUid;
    605         }
    606 
    607         public List<OpEntry> getOps() {
    608             return mEntries;
    609         }
    610 
    611         @Override
    612         public int describeContents() {
    613             return 0;
    614         }
    615 
    616         @Override
    617         public void writeToParcel(Parcel dest, int flags) {
    618             dest.writeString(mPackageName);
    619             dest.writeInt(mUid);
    620             dest.writeInt(mEntries.size());
    621             for (int i=0; i<mEntries.size(); i++) {
    622                 mEntries.get(i).writeToParcel(dest, flags);
    623             }
    624         }
    625 
    626         PackageOps(Parcel source) {
    627             mPackageName = source.readString();
    628             mUid = source.readInt();
    629             mEntries = new ArrayList<OpEntry>();
    630             final int N = source.readInt();
    631             for (int i=0; i<N; i++) {
    632                 mEntries.add(OpEntry.CREATOR.createFromParcel(source));
    633             }
    634         }
    635 
    636         public static final Creator<PackageOps> CREATOR = new Creator<PackageOps>() {
    637             @Override public PackageOps createFromParcel(Parcel source) {
    638                 return new PackageOps(source);
    639             }
    640 
    641             @Override public PackageOps[] newArray(int size) {
    642                 return new PackageOps[size];
    643             }
    644         };
    645     }
    646 
    647     /**
    648      * Class holding the information about one unique operation of an application.
    649      * @hide
    650      */
    651     public static class OpEntry implements Parcelable {
    652         private final int mOp;
    653         private final int mMode;
    654         private final long mTime;
    655         private final long mRejectTime;
    656         private final int mDuration;
    657 
    658         public OpEntry(int op, int mode, long time, long rejectTime, int duration) {
    659             mOp = op;
    660             mMode = mode;
    661             mTime = time;
    662             mRejectTime = rejectTime;
    663             mDuration = duration;
    664         }
    665 
    666         public int getOp() {
    667             return mOp;
    668         }
    669 
    670         public int getMode() {
    671             return mMode;
    672         }
    673 
    674         public long getTime() {
    675             return mTime;
    676         }
    677 
    678         public long getRejectTime() {
    679             return mRejectTime;
    680         }
    681 
    682         public boolean isRunning() {
    683             return mDuration == -1;
    684         }
    685 
    686         public int getDuration() {
    687             return mDuration == -1 ? (int)(System.currentTimeMillis()-mTime) : mDuration;
    688         }
    689 
    690         @Override
    691         public int describeContents() {
    692             return 0;
    693         }
    694 
    695         @Override
    696         public void writeToParcel(Parcel dest, int flags) {
    697             dest.writeInt(mOp);
    698             dest.writeInt(mMode);
    699             dest.writeLong(mTime);
    700             dest.writeLong(mRejectTime);
    701             dest.writeInt(mDuration);
    702         }
    703 
    704         OpEntry(Parcel source) {
    705             mOp = source.readInt();
    706             mMode = source.readInt();
    707             mTime = source.readLong();
    708             mRejectTime = source.readLong();
    709             mDuration = source.readInt();
    710         }
    711 
    712         public static final Creator<OpEntry> CREATOR = new Creator<OpEntry>() {
    713             @Override public OpEntry createFromParcel(Parcel source) {
    714                 return new OpEntry(source);
    715             }
    716 
    717             @Override public OpEntry[] newArray(int size) {
    718                 return new OpEntry[size];
    719             }
    720         };
    721     }
    722 
    723     /**
    724      * Callback for notification of changes to operation state.
    725      */
    726     public interface OnOpChangedListener {
    727         public void onOpChanged(String op, String packageName);
    728     }
    729 
    730     /**
    731      * Callback for notification of changes to operation state.
    732      * This allows you to see the raw op codes instead of strings.
    733      * @hide
    734      */
    735     public static class OnOpChangedInternalListener implements OnOpChangedListener {
    736         public void onOpChanged(String op, String packageName) { }
    737         public void onOpChanged(int op, String packageName) { }
    738     }
    739 
    740     AppOpsManager(Context context, IAppOpsService service) {
    741         mContext = context;
    742         mService = service;
    743     }
    744 
    745     /**
    746      * Retrieve current operation state for all applications.
    747      *
    748      * @param ops The set of operations you are interested in, or null if you want all of them.
    749      * @hide
    750      */
    751     public List<AppOpsManager.PackageOps> getPackagesForOps(int[] ops) {
    752         try {
    753             return mService.getPackagesForOps(ops);
    754         } catch (RemoteException e) {
    755         }
    756         return null;
    757     }
    758 
    759     /**
    760      * Retrieve current operation state for one application.
    761      *
    762      * @param uid The uid of the application of interest.
    763      * @param packageName The name of the application of interest.
    764      * @param ops The set of operations you are interested in, or null if you want all of them.
    765      * @hide
    766      */
    767     public List<AppOpsManager.PackageOps> getOpsForPackage(int uid, String packageName, int[] ops) {
    768         try {
    769             return mService.getOpsForPackage(uid, packageName, ops);
    770         } catch (RemoteException e) {
    771         }
    772         return null;
    773     }
    774 
    775     /** @hide */
    776     public void setMode(int code, int uid, String packageName, int mode) {
    777         try {
    778             mService.setMode(code, uid, packageName, mode);
    779         } catch (RemoteException e) {
    780         }
    781     }
    782 
    783     /** @hide */
    784     public void resetAllModes() {
    785         try {
    786             mService.resetAllModes();
    787         } catch (RemoteException e) {
    788         }
    789     }
    790 
    791     /**
    792      * Monitor for changes to the operating mode for the given op in the given app package.
    793      * @param op The operation to monitor, one of OPSTR_*.
    794      * @param packageName The name of the application to monitor.
    795      * @param callback Where to report changes.
    796      */
    797     public void startWatchingMode(String op, String packageName,
    798             final OnOpChangedListener callback) {
    799         startWatchingMode(strOpToOp(op), packageName, callback);
    800     }
    801 
    802     /**
    803      * Monitor for changes to the operating mode for the given op in the given app package.
    804      * @param op The operation to monitor, one of OP_*.
    805      * @param packageName The name of the application to monitor.
    806      * @param callback Where to report changes.
    807      * @hide
    808      */
    809     public void startWatchingMode(int op, String packageName, final OnOpChangedListener callback) {
    810         synchronized (mModeWatchers) {
    811             IAppOpsCallback cb = mModeWatchers.get(callback);
    812             if (cb == null) {
    813                 cb = new IAppOpsCallback.Stub() {
    814                     public void opChanged(int op, String packageName) {
    815                         if (callback instanceof OnOpChangedInternalListener) {
    816                             ((OnOpChangedInternalListener)callback).onOpChanged(op, packageName);
    817                         }
    818                         if (sOpToString[op] != null) {
    819                             callback.onOpChanged(sOpToString[op], packageName);
    820                         }
    821                     }
    822                 };
    823                 mModeWatchers.put(callback, cb);
    824             }
    825             try {
    826                 mService.startWatchingMode(op, packageName, cb);
    827             } catch (RemoteException e) {
    828             }
    829         }
    830     }
    831 
    832     /**
    833      * Stop monitoring that was previously started with {@link #startWatchingMode}.  All
    834      * monitoring associated with this callback will be removed.
    835      */
    836     public void stopWatchingMode(OnOpChangedListener callback) {
    837         synchronized (mModeWatchers) {
    838             IAppOpsCallback cb = mModeWatchers.get(callback);
    839             if (cb != null) {
    840                 try {
    841                     mService.stopWatchingMode(cb);
    842                 } catch (RemoteException e) {
    843                 }
    844             }
    845         }
    846     }
    847 
    848     private String buildSecurityExceptionMsg(int op, int uid, String packageName) {
    849         return packageName + " from uid " + uid + " not allowed to perform " + sOpNames[op];
    850     }
    851 
    852     private int strOpToOp(String op) {
    853         Integer val = sOpStrToOp.get(op);
    854         if (val == null) {
    855             throw new IllegalArgumentException("Unknown operation string: " + op);
    856         }
    857         return val;
    858     }
    859 
    860     /**
    861      * Do a quick check for whether an application might be able to perform an operation.
    862      * This is <em>not</em> a security check; you must use {@link #noteOp(String, int, String)}
    863      * or {@link #startOp(String, int, String)} for your actual security checks, which also
    864      * ensure that the given uid and package name are consistent.  This function can just be
    865      * used for a quick check to see if an operation has been disabled for the application,
    866      * as an early reject of some work.  This does not modify the time stamp or other data
    867      * about the operation.
    868      * @param op The operation to check.  One of the OPSTR_* constants.
    869      * @param uid The user id of the application attempting to perform the operation.
    870      * @param packageName The name of the application attempting to perform the operation.
    871      * @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or
    872      * {@link #MODE_IGNORED} if it is not allowed and should be silently ignored (without
    873      * causing the app to crash).
    874      * @throws SecurityException If the app has been configured to crash on this op.
    875      */
    876     public int checkOp(String op, int uid, String packageName) {
    877         return checkOp(strOpToOp(op), uid, packageName);
    878     }
    879 
    880     /**
    881      * Like {@link #checkOp but instead of throwing a {@link SecurityException} it
    882      * returns {@link #MODE_ERRORED}.
    883      */
    884     public int checkOpNoThrow(String op, int uid, String packageName) {
    885         return checkOpNoThrow(strOpToOp(op), uid, packageName);
    886     }
    887 
    888     /**
    889      * Make note of an application performing an operation.  Note that you must pass
    890      * in both the uid and name of the application to be checked; this function will verify
    891      * that these two match, and if not, return {@link #MODE_IGNORED}.  If this call
    892      * succeeds, the last execution time of the operation for this app will be updated to
    893      * the current time.
    894      * @param op The operation to note.  One of the OPSTR_* constants.
    895      * @param uid The user id of the application attempting to perform the operation.
    896      * @param packageName The name of the application attempting to perform the operation.
    897      * @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or
    898      * {@link #MODE_IGNORED} if it is not allowed and should be silently ignored (without
    899      * causing the app to crash).
    900      * @throws SecurityException If the app has been configured to crash on this op.
    901      */
    902     public int noteOp(String op, int uid, String packageName) {
    903         return noteOp(strOpToOp(op), uid, packageName);
    904     }
    905 
    906     /**
    907      * Like {@link #noteOp} but instead of throwing a {@link SecurityException} it
    908      * returns {@link #MODE_ERRORED}.
    909      */
    910     public int noteOpNoThrow(String op, int uid, String packageName) {
    911         return noteOpNoThrow(strOpToOp(op), uid, packageName);
    912     }
    913 
    914     /**
    915      * Report that an application has started executing a long-running operation.  Note that you
    916      * must pass in both the uid and name of the application to be checked; this function will
    917      * verify that these two match, and if not, return {@link #MODE_IGNORED}.  If this call
    918      * succeeds, the last execution time of the operation for this app will be updated to
    919      * the current time and the operation will be marked as "running".  In this case you must
    920      * later call {@link #finishOp(String, int, String)} to report when the application is no
    921      * longer performing the operation.
    922      * @param op The operation to start.  One of the OPSTR_* constants.
    923      * @param uid The user id of the application attempting to perform the operation.
    924      * @param packageName The name of the application attempting to perform the operation.
    925      * @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or
    926      * {@link #MODE_IGNORED} if it is not allowed and should be silently ignored (without
    927      * causing the app to crash).
    928      * @throws SecurityException If the app has been configured to crash on this op.
    929      */
    930     public int startOp(String op, int uid, String packageName) {
    931         return startOp(strOpToOp(op), uid, packageName);
    932     }
    933 
    934     /**
    935      * Like {@link #startOp} but instead of throwing a {@link SecurityException} it
    936      * returns {@link #MODE_ERRORED}.
    937      */
    938     public int startOpNoThrow(String op, int uid, String packageName) {
    939         return startOpNoThrow(strOpToOp(op), uid, packageName);
    940     }
    941 
    942     /**
    943      * Report that an application is no longer performing an operation that had previously
    944      * been started with {@link #startOp(String, int, String)}.  There is no validation of input
    945      * or result; the parameters supplied here must be the exact same ones previously passed
    946      * in when starting the operation.
    947      */
    948     public void finishOp(String op, int uid, String packageName) {
    949         finishOp(strOpToOp(op), uid, packageName);
    950     }
    951 
    952     /**
    953      * Do a quick check for whether an application might be able to perform an operation.
    954      * This is <em>not</em> a security check; you must use {@link #noteOp(int, int, String)}
    955      * or {@link #startOp(int, int, String)} for your actual security checks, which also
    956      * ensure that the given uid and package name are consistent.  This function can just be
    957      * used for a quick check to see if an operation has been disabled for the application,
    958      * as an early reject of some work.  This does not modify the time stamp or other data
    959      * about the operation.
    960      * @param op The operation to check.  One of the OP_* constants.
    961      * @param uid The user id of the application attempting to perform the operation.
    962      * @param packageName The name of the application attempting to perform the operation.
    963      * @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or
    964      * {@link #MODE_IGNORED} if it is not allowed and should be silently ignored (without
    965      * causing the app to crash).
    966      * @throws SecurityException If the app has been configured to crash on this op.
    967      * @hide
    968      */
    969     public int checkOp(int op, int uid, String packageName) {
    970         try {
    971             int mode = mService.checkOperation(op, uid, packageName);
    972             if (mode == MODE_ERRORED) {
    973                 throw new SecurityException(buildSecurityExceptionMsg(op, uid, packageName));
    974             }
    975             return mode;
    976         } catch (RemoteException e) {
    977         }
    978         return MODE_IGNORED;
    979     }
    980 
    981     /**
    982      * Like {@link #checkOp} but instead of throwing a {@link SecurityException} it
    983      * returns {@link #MODE_ERRORED}.
    984      * @hide
    985      */
    986     public int checkOpNoThrow(int op, int uid, String packageName) {
    987         try {
    988             return mService.checkOperation(op, uid, packageName);
    989         } catch (RemoteException e) {
    990         }
    991         return MODE_IGNORED;
    992     }
    993 
    994     /**
    995      * Do a quick check to validate if a package name belongs to a UID.
    996      *
    997      * @throws SecurityException if the package name doesn't belong to the given
    998      *             UID, or if ownership cannot be verified.
    999      */
   1000     public void checkPackage(int uid, String packageName) {
   1001         try {
   1002             if (mService.checkPackage(uid, packageName) != MODE_ALLOWED) {
   1003                 throw new SecurityException(
   1004                         "Package " + packageName + " does not belong to " + uid);
   1005             }
   1006         } catch (RemoteException e) {
   1007             throw new SecurityException("Unable to verify package ownership", e);
   1008         }
   1009     }
   1010 
   1011     /**
   1012      * Make note of an application performing an operation.  Note that you must pass
   1013      * in both the uid and name of the application to be checked; this function will verify
   1014      * that these two match, and if not, return {@link #MODE_IGNORED}.  If this call
   1015      * succeeds, the last execution time of the operation for this app will be updated to
   1016      * the current time.
   1017      * @param op The operation to note.  One of the OP_* constants.
   1018      * @param uid The user id of the application attempting to perform the operation.
   1019      * @param packageName The name of the application attempting to perform the operation.
   1020      * @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or
   1021      * {@link #MODE_IGNORED} if it is not allowed and should be silently ignored (without
   1022      * causing the app to crash).
   1023      * @throws SecurityException If the app has been configured to crash on this op.
   1024      * @hide
   1025      */
   1026     public int noteOp(int op, int uid, String packageName) {
   1027         try {
   1028             int mode = mService.noteOperation(op, uid, packageName);
   1029             if (mode == MODE_ERRORED) {
   1030                 throw new SecurityException(buildSecurityExceptionMsg(op, uid, packageName));
   1031             }
   1032             return mode;
   1033         } catch (RemoteException e) {
   1034         }
   1035         return MODE_IGNORED;
   1036     }
   1037 
   1038     /**
   1039      * Like {@link #noteOp} but instead of throwing a {@link SecurityException} it
   1040      * returns {@link #MODE_ERRORED}.
   1041      * @hide
   1042      */
   1043     public int noteOpNoThrow(int op, int uid, String packageName) {
   1044         try {
   1045             return mService.noteOperation(op, uid, packageName);
   1046         } catch (RemoteException e) {
   1047         }
   1048         return MODE_IGNORED;
   1049     }
   1050 
   1051     /** @hide */
   1052     public int noteOp(int op) {
   1053         return noteOp(op, Process.myUid(), mContext.getOpPackageName());
   1054     }
   1055 
   1056     /** @hide */
   1057     public static IBinder getToken(IAppOpsService service) {
   1058         synchronized (AppOpsManager.class) {
   1059             if (sToken != null) {
   1060                 return sToken;
   1061             }
   1062             try {
   1063                 sToken = service.getToken(new Binder());
   1064             } catch (RemoteException e) {
   1065                 // System is dead, whatevs.
   1066             }
   1067             return sToken;
   1068         }
   1069     }
   1070 
   1071     /**
   1072      * Report that an application has started executing a long-running operation.  Note that you
   1073      * must pass in both the uid and name of the application to be checked; this function will
   1074      * verify that these two match, and if not, return {@link #MODE_IGNORED}.  If this call
   1075      * succeeds, the last execution time of the operation for this app will be updated to
   1076      * the current time and the operation will be marked as "running".  In this case you must
   1077      * later call {@link #finishOp(int, int, String)} to report when the application is no
   1078      * longer performing the operation.
   1079      * @param op The operation to start.  One of the OP_* constants.
   1080      * @param uid The user id of the application attempting to perform the operation.
   1081      * @param packageName The name of the application attempting to perform the operation.
   1082      * @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or
   1083      * {@link #MODE_IGNORED} if it is not allowed and should be silently ignored (without
   1084      * causing the app to crash).
   1085      * @throws SecurityException If the app has been configured to crash on this op.
   1086      * @hide
   1087      */
   1088     public int startOp(int op, int uid, String packageName) {
   1089         try {
   1090             int mode = mService.startOperation(getToken(mService), op, uid, packageName);
   1091             if (mode == MODE_ERRORED) {
   1092                 throw new SecurityException(buildSecurityExceptionMsg(op, uid, packageName));
   1093             }
   1094             return mode;
   1095         } catch (RemoteException e) {
   1096         }
   1097         return MODE_IGNORED;
   1098     }
   1099 
   1100     /**
   1101      * Like {@link #startOp} but instead of throwing a {@link SecurityException} it
   1102      * returns {@link #MODE_ERRORED}.
   1103      * @hide
   1104      */
   1105     public int startOpNoThrow(int op, int uid, String packageName) {
   1106         try {
   1107             return mService.startOperation(getToken(mService), op, uid, packageName);
   1108         } catch (RemoteException e) {
   1109         }
   1110         return MODE_IGNORED;
   1111     }
   1112 
   1113     /** @hide */
   1114     public int startOp(int op) {
   1115         return startOp(op, Process.myUid(), mContext.getOpPackageName());
   1116     }
   1117 
   1118     /**
   1119      * Report that an application is no longer performing an operation that had previously
   1120      * been started with {@link #startOp(int, int, String)}.  There is no validation of input
   1121      * or result; the parameters supplied here must be the exact same ones previously passed
   1122      * in when starting the operation.
   1123      * @hide
   1124      */
   1125     public void finishOp(int op, int uid, String packageName) {
   1126         try {
   1127             mService.finishOperation(getToken(mService), op, uid, packageName);
   1128         } catch (RemoteException e) {
   1129         }
   1130     }
   1131 
   1132     /** @hide */
   1133     public void finishOp(int op) {
   1134         finishOp(op, Process.myUid(), mContext.getOpPackageName());
   1135     }
   1136 }
   1137