Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6328145d authored by Danesh M's avatar Danesh M Committed by Gerrit Code Review
Browse files

Merge "AppOpsService: Add MODE_ASK support to AppOps." into cm-10.2

parents 3d901f7d 45fbca45
Loading
Loading
Loading
Loading
+51 −0
Original line number Original line Diff line number Diff line
/*
/*
 * Copyright (c) 2013, The Linux Foundation. All rights reserved.
 * Not a Contribution.
 *
 * Copyright (C) 2012 The Android Open Source Project
 * Copyright (C) 2012 The Android Open Source Project
 *
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * Licensed under the Apache License, Version 2.0 (the "License");
@@ -59,6 +62,7 @@ public class AppOpsManager {
    public static final int MODE_ALLOWED = 0;
    public static final int MODE_ALLOWED = 0;
    public static final int MODE_IGNORED = 1;
    public static final int MODE_IGNORED = 1;
    public static final int MODE_ERRORED = 2;
    public static final int MODE_ERRORED = 2;
    public static final int MODE_ASK     = 3;


    // when adding one of these:
    // when adding one of these:
    //  - increment _NUM_OP
    //  - increment _NUM_OP
@@ -99,6 +103,46 @@ public class AppOpsManager {
    /** @hide */
    /** @hide */
    public static final int _NUM_OP = 31;
    public static final int _NUM_OP = 31;


    /**
     * Map to check if each operation is strict or not, to determine default
     * value of each operation.
     * If strict then AppOpsService should assign MODE_ASK value to operation
     * by default.
     */
    private static boolean[] sOpStrict = new boolean[] {
        true,   //OP_COARSE_LOCATION
        true,   //OP_FINE_LOCATION
        true,   //OP_GPS
        false,  //OP_VIBRATE
        true,   //OP_READ_CONTACTS
        true,   //OP_WRITE_CONTACTS
        true,   //OP_READ_CALL_LOG
        true,   //OP_WRITE_CALL_LOG
        false,  //OP_READ_CALENDAR
        false,  //OP_WRITE_CALENDAR
        true,   //OP_WIFI_SCAN
        false,  //OP_POST_NOTIFICATION
        false,  //OP_NEIGHBORING_CELLS
        true,   //OP_CALL_PHONE
        true,   //OP_READ_SMS
        true,   //OP_WRITE_SMS
        true,   //OP_RECEIVE_SMS
        false,  //OP_RECEIVE_EMERGECY_SMS
        true,   //OP_RECEIVE_MMS
        false,  //OP_RECEIVE_WAP_PUSH
        true,   //OP_SEND_SMS
        true,   //OP_READ_ICC_SMS
        true,   //OP_WRITE_ICC_SMS
        false,  //OP_WRITE_SETTINGS
        false,  //OP_SYSTEM_ALERT_WINDOW
        false,  //OP_ACCESS_NOTIFICATIONS
        true,   //OP_CAMERA
        true,   //OP_RECORD_AUDIO
        true,   //OP_PLAY_AUDIO
        false,  //OP_READ_CLIPBOARD
        false,  //OP_WRITE_CLIPBOARD
    };

    /**
    /**
     * This maps each operation to the operation that serves as the
     * This maps each operation to the operation that serves as the
     * switch to determine whether it is allowed.  Generally this is
     * switch to determine whether it is allowed.  Generally this is
@@ -217,6 +261,13 @@ public class AppOpsManager {
            null, // no permission for writing clipboard
            null, // no permission for writing clipboard
    };
    };


    /**
     * Check if given operation is strict or not.
     */
    public static boolean opStrict(int op) {
        return sOpStrict[op];
    }

    /**
    /**
     * Retrieve the op switch that controls the given operation.
     * Retrieve the op switch that controls the given operation.
     */
     */
+46 −0
Original line number Original line Diff line number Diff line
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
** Copyright (c) 2013, The Linux Foundation. All rights reserved.
** Not a Contribution.
**
** Copyright 2012 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.
*/
-->

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/parentPanel"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginLeft="8dip"
    android:layout_marginRight="8dip"
    android:orientation="vertical">

    <TextView android:id="@+id/permission_text"
        style="?android:attr/textAppearanceMedium"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingLeft="20dip"
        android:paddingRight="20dip"
        android:paddingTop="16dip"
        android:paddingBottom="16dip" />

    <CheckBox android:id="@+id/permission_remember_choice_checkbox"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/save_password_remember" />

</LinearLayout>
+34 −0
Original line number Original line Diff line number Diff line
@@ -52,4 +52,38 @@
        <item>2</item>
        <item>2</item>
    </string-array>
    </string-array>


    <!-- User display names for app ops codes -->
    <string-array name="app_ops_labels">
        <item>Trying to access location</item>
        <item>Trying to access location</item>
        <item>Trying to access location</item>
        <item>Trying to use vibrate</item>
        <item>Trying to read contacts</item>
        <item>Trying to modify contacts</item>
        <item>Trying to read call log</item>
        <item>Trying to modify call log</item>
        <item>Trying to read calendar</item>
        <item>Trying to modify calendar</item>
        <item>Trying to access location</item>
        <item>Trying to post notification</item>
        <item>Trying to access location</item>
        <item>Trying to make phone call</item>
        <item>Trying to read SMS/MMS</item>
        <item>Trying to write/modify SMS/MMS</item>
        <item>Trying to receive SMS/MMS</item>
        <item>Trying to receive SMS/MMS</item>
        <item>Trying to receive SMS/MMS</item>
        <item>Trying to receive SMS/MMS</item>
        <item>Trying to send SMS/MMS</item>
        <item>Trying to read SMS/MMS</item>
        <item>Trying to write/modify SMS/MMS</item>
        <item>Trying to modify settings</item>
        <item>Trying to draw on top</item>
        <item>Trying to access notifications</item>
        <item>Trying to access Camera</item>
        <item>Trying to record audio</item>
        <item>Trying to play audio</item>
        <item>Trying to read clipboard</item>
        <item>Trying to modify clipboard</item>
    </string-array>
</resources>
</resources>
+11 −1
Original line number Original line Diff line number Diff line
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<!--
<!--
/* Copyright 2012, The Android Open Source Project
/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
** Not a Contribution.
**
** Copyright 2012, The Android Open Source Project
**
**
** Licensed under the Apache License, Version 2.0 (the "License");
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** you may not use this file except in compliance with the License.
@@ -218,6 +221,8 @@
  <java-symbol type="id" name="sms_short_code_remember_undo_instruction" />
  <java-symbol type="id" name="sms_short_code_remember_undo_instruction" />
  <java-symbol type="id" name="breadcrumb_section" />
  <java-symbol type="id" name="breadcrumb_section" />
  <java-symbol type="id" name="action_bar_spinner" />
  <java-symbol type="id" name="action_bar_spinner" />
  <java-symbol type="id" name="permission_text" />
  <java-symbol type="id" name="permission_remember_choice_checkbox" />


  <java-symbol type="attr" name="actionModeShareDrawable" />
  <java-symbol type="attr" name="actionModeShareDrawable" />
  <java-symbol type="attr" name="alertDialogCenterButtons" />
  <java-symbol type="attr" name="alertDialogCenterButtons" />
@@ -334,9 +339,11 @@
  <java-symbol type="string" name="addToDictionary" />
  <java-symbol type="string" name="addToDictionary" />
  <java-symbol type="string" name="action_bar_home_description" />
  <java-symbol type="string" name="action_bar_home_description" />
  <java-symbol type="string" name="action_bar_up_description" />
  <java-symbol type="string" name="action_bar_up_description" />
  <java-symbol type="string" name="allow" />
  <java-symbol type="string" name="app_running_notification_title" />
  <java-symbol type="string" name="app_running_notification_title" />
  <java-symbol type="string" name="app_running_notification_text" />
  <java-symbol type="string" name="app_running_notification_text" />
  <java-symbol type="string" name="delete" />
  <java-symbol type="string" name="delete" />
  <java-symbol type="string" name="deny" />
  <java-symbol type="string" name="deleteText" />
  <java-symbol type="string" name="deleteText" />
  <java-symbol type="string" name="ellipsis_two_dots" />
  <java-symbol type="string" name="ellipsis_two_dots" />
  <java-symbol type="string" name="ellipsis" />
  <java-symbol type="string" name="ellipsis" />
@@ -346,6 +353,7 @@
  <java-symbol type="string" name="menu_enter_shortcut_label" />
  <java-symbol type="string" name="menu_enter_shortcut_label" />
  <java-symbol type="string" name="menu_space_shortcut_label" />
  <java-symbol type="string" name="menu_space_shortcut_label" />
  <java-symbol type="string" name="notification_title" />
  <java-symbol type="string" name="notification_title" />
  <java-symbol type="string" name="permission_request_notification_title" />
  <java-symbol type="string" name="permission_request_notification_with_subtitle" />
  <java-symbol type="string" name="permission_request_notification_with_subtitle" />
  <java-symbol type="string" name="prepend_shortcut_label" />
  <java-symbol type="string" name="prepend_shortcut_label" />
  <java-symbol type="string" name="replace" />
  <java-symbol type="string" name="replace" />
@@ -1122,6 +1130,7 @@
  <java-symbol type="layout" name="locale_picker_item" />
  <java-symbol type="layout" name="locale_picker_item" />
  <java-symbol type="layout" name="media_controller" />
  <java-symbol type="layout" name="media_controller" />
  <java-symbol type="layout" name="overlay_display_window" />
  <java-symbol type="layout" name="overlay_display_window" />
  <java-symbol type="layout" name="permission_confirmation_dialog" />
  <java-symbol type="layout" name="preference" />
  <java-symbol type="layout" name="preference" />
  <java-symbol type="layout" name="preference_header_item" />
  <java-symbol type="layout" name="preference_header_item" />
  <java-symbol type="layout" name="preference_list_content" />
  <java-symbol type="layout" name="preference_list_content" />
@@ -1556,6 +1565,7 @@
  <java-symbol type="anim" name="rotation_animation_enter" />
  <java-symbol type="anim" name="rotation_animation_enter" />
  <java-symbol type="anim" name="shrink_fade_out_center" />
  <java-symbol type="anim" name="shrink_fade_out_center" />
  <java-symbol type="anim" name="grow_fade_in_center" />
  <java-symbol type="anim" name="grow_fade_in_center" />
  <java-symbol type="array" name="app_ops_labels" />
  <java-symbol type="array" name="config_autoBrightnessButtonBacklightValues" />
  <java-symbol type="array" name="config_autoBrightnessButtonBacklightValues" />
  <java-symbol type="array" name="config_autoBrightnessKeyboardBacklightValues" />
  <java-symbol type="array" name="config_autoBrightnessKeyboardBacklightValues" />
  <java-symbol type="array" name="config_autoBrightnessLcdBacklightValues" />
  <java-symbol type="array" name="config_autoBrightnessLcdBacklightValues" />
+226 −45
Original line number Original line Diff line number Diff line
/*
/*
 * Copyright (c) 2013, The Linux Foundation. All rights reserved.
 * Not a Contribution.
 *
 * Copyright (C) 2012 The Android Open Source Project
 * Copyright (C) 2012 The Android Open Source Project
 *
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * Licensed under the Apache License, Version 2.0 (the "License");
@@ -30,16 +33,21 @@ import java.util.List;
import java.util.Map;
import java.util.Map;


import android.app.AppOpsManager;
import android.app.AppOpsManager;
import android.app.Dialog;
import android.content.Context;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.AsyncTask;
import android.os.AsyncTask;
import android.os.Binder;
import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
import android.os.Handler;
import android.os.IBinder;
import android.os.IBinder;
import android.os.Message;
import android.os.Process;
import android.os.Process;
import android.os.RemoteException;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.ServiceManager;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.UserHandle;
import android.util.AtomicFile;
import android.util.AtomicFile;
import android.util.Log;
import android.util.Log;
@@ -58,9 +66,12 @@ import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;
import org.xmlpull.v1.XmlSerializer;


import com.android.server.PermissionDialogResult.Result;

public class AppOpsService extends IAppOpsService.Stub {
public class AppOpsService extends IAppOpsService.Stub {
    static final String TAG = "AppOps";
    static final String TAG = "AppOps";
    static final boolean DEBUG = false;
    static final boolean DEBUG = false;
    static final String STRICT_PERMISSION_PROPERTY = "persist.sys.strict_op_enable";


    // Write at most every 30 minutes.
    // Write at most every 30 minutes.
    static final long WRITE_DELAY = DEBUG ? 1000 : 30*60*1000;
    static final long WRITE_DELAY = DEBUG ? 1000 : 30*60*1000;
@@ -68,6 +79,9 @@ public class AppOpsService extends IAppOpsService.Stub {
    Context mContext;
    Context mContext;
    final AtomicFile mFile;
    final AtomicFile mFile;
    final Handler mHandler;
    final Handler mHandler;
    final boolean mStrictEnable;

    static final int SHOW_PERMISSION_DIALOG = 1;


    private static final int[] PRIVACY_GUARD_OP_STATES = new int[] {
    private static final int[] PRIVACY_GUARD_OP_STATES = new int[] {
        AppOpsManager.OP_COARSE_LOCATION,
        AppOpsManager.OP_COARSE_LOCATION,
@@ -109,14 +123,23 @@ public class AppOpsService extends IAppOpsService.Stub {
    public final static class Op {
    public final static class Op {
        public final int op;
        public final int op;
        public int mode;
        public int mode;
        public final int defaultMode;
        public int duration;
        public int duration;
        public long time;
        public long time;
        public long rejectTime;
        public long rejectTime;
        public int nesting;
        public int nesting;
        public int tempNesting;
        public PermissionDialogResult dialogResult;


        public Op(int _op) {
        public Op(int _op, boolean strict) {
            op = _op;
            op = _op;
            if (!strict) {
                mode = AppOpsManager.MODE_ALLOWED;
                mode = AppOpsManager.MODE_ALLOWED;
            } else {
                mode = AppOpsManager.MODE_ASK;
            }
            dialogResult = new PermissionDialogResult();
            defaultMode = mode;
        }
        }
    }
    }


@@ -149,8 +172,31 @@ public class AppOpsService extends IAppOpsService.Stub {
    }
    }


    public AppOpsService(File storagePath) {
    public AppOpsService(File storagePath) {
        mStrictEnable = "true".equals(SystemProperties.get(STRICT_PERMISSION_PROPERTY));
        mFile = new AtomicFile(storagePath);
        mFile = new AtomicFile(storagePath);
        mHandler = new Handler();
        mHandler = new Handler() {
            public void handleMessage(Message msg) {
                switch (msg.what) {
                case SHOW_PERMISSION_DIALOG: {
                    Bundle data = msg.getData();
                    synchronized (this) {
                        Op op = (Op) msg.obj;
                        Result res = (Result) data.getParcelable("result");
                        op.dialogResult.register(res);
                        if (op.dialogResult.mDialog == null) {
                            Integer code = data.getInt("code");
                            Integer uid  = data.getInt("uid");
                            String packageName = data.getString("packageName");
                            PermissionDialog d = new PermissionDialog(mContext, AppOpsService.this,
                                    code, uid, packageName);
                            op.dialogResult.mDialog = d;
                            d.show();
                        }
                    }
                }break;
                }
            }
        };
        readState();
        readState();
    }
    }


@@ -341,11 +387,13 @@ public class AppOpsService extends IAppOpsService.Stub {
                        }
                        }
                        repCbs.addAll(cbs);
                        repCbs.addAll(cbs);
                    }
                    }
                    if (mode == AppOpsManager.MODE_ALLOWED) {

                    if (mode == op.defaultMode) {
                        // If going into the default mode, prune this op
                        // If going into the default mode, prune this op
                        // if there is nothing else interesting in it.
                        // if there is nothing else interesting in it.
                        pruneOp(op, uid, packageName);
                        pruneOp(op, uid, packageName);
                    }
                    }

                    scheduleWriteNowLocked();
                    scheduleWriteNowLocked();
                }
                }
            }
            }
@@ -395,8 +443,8 @@ public class AppOpsService extends IAppOpsService.Stub {
                    Ops pkgOps = ent.getValue();
                    Ops pkgOps = ent.getValue();
                    for (int j=0; j<pkgOps.size(); j++) {
                    for (int j=0; j<pkgOps.size(); j++) {
                        Op curOp = pkgOps.valueAt(j);
                        Op curOp = pkgOps.valueAt(j);
                        if (curOp.mode != AppOpsManager.MODE_ALLOWED) {
                        if (curOp.mode != curOp.defaultMode) {
                            curOp.mode = AppOpsManager.MODE_ALLOWED;
                            curOp.mode = curOp.defaultMode;
                            changed = true;
                            changed = true;
                            callbacks = addCallbacks(callbacks, packageName, curOp.op,
                            callbacks = addCallbacks(callbacks, packageName, curOp.op,
                                    mOpModeWatchers.get(curOp.op));
                                    mOpModeWatchers.get(curOp.op));
@@ -481,14 +529,130 @@ public class AppOpsService extends IAppOpsService.Stub {
        }
        }
    }
    }


    private boolean isStrict(int code, int uid, String packageName) {
        if (!mStrictEnable) {
            return false;
        }
        return ((uid > Process.FIRST_APPLICATION_UID) &&
                (AppOpsManager.opStrict(code)));
    }

    private void recordOperationLocked(int code, int uid, String packageName, int mode) {
        int switchCode = AppOpsManager.opToSwitch(code);
        Op op = getOpLocked(switchCode, uid, packageName, false);
        if (op != null) {
            if (mode == AppOpsManager.MODE_IGNORED) {
                if (DEBUG) Log.d(TAG, "recordOperation: reject #" + mode + " for code "
                        + switchCode + " (" + code + ") uid " + uid + " package " + packageName);
                op.rejectTime = System.currentTimeMillis();
            } else if (mode == AppOpsManager.MODE_ALLOWED) {
                if (DEBUG) Log.d(TAG, "recordOperation: allowing code " + code + " uid " + uid
                        + " package " + packageName);
                op.time = System.currentTimeMillis();
                op.rejectTime = 0;
            }
        }
    }

    public void notifyOperation(int code, int uid, String packageName, int mode,
            boolean remember) {
        verifyIncomingUid(uid);
        verifyIncomingOp(code);
        ArrayList<Callback> repCbs = null;
        code = AppOpsManager.opToSwitch(code);
        synchronized (this) {
            Op op = getOpLocked(code, uid, packageName, true);
            if (op != null) {
                // Record this mode
                recordOperationLocked(code, uid, packageName, mode);

                // Increase nesting for all pending startOperation requests
                if(mode == AppOpsManager.MODE_ALLOWED) {
                   if (op.nesting == 0) {
                        op.time = System.currentTimeMillis();
                        op.rejectTime = 0;
                        op.duration = -1;
                    }
                    op.nesting = op.nesting + op.tempNesting;
                }
                // Reset tempNesting
                op.tempNesting = 0;

                // Send result to all waiting client
                op.dialogResult.notifyAll(mode);
                op.dialogResult.mDialog = null;

                // if User selected to remember her choice
                if (remember) {
                    if (op.mode != mode) {
                        op.mode = mode;
                        ArrayList<Callback> cbs = mOpModeWatchers.get(code);
                        if (cbs != null) {
                            if (repCbs == null) {
                                repCbs = new ArrayList<Callback>();
                            }
                            repCbs.addAll(cbs);
                        }
                        cbs = mPackageModeWatchers.get(packageName);
                        if (cbs != null) {
                            if (repCbs == null) {
                                repCbs = new ArrayList<Callback>();
                            }
                            repCbs.addAll(cbs);
                        }

                        if (mode == op.defaultMode) {
                            // If going into the default mode, prune this op
                            // if there is nothing else interesting in it.
                            pruneOp(op, uid, packageName);
                        }

                        scheduleWriteNowLocked();
                    }
                }
            }
        }
        if (repCbs != null) {
            for (int i=0; i<repCbs.size(); i++) {
                try {
                    repCbs.get(i).mCallback.opChanged(code, packageName);
                } catch (RemoteException e) {
                }
            }
        }

    }

    private Result askOperationLocked(int code, int uid, String packageName, Op op) {
        Result result = new Result();
        final long origId = Binder.clearCallingIdentity();
        Message msg = Message.obtain();
        msg.what = SHOW_PERMISSION_DIALOG;
        Bundle data = new Bundle();
        data.putParcelable("result", result);
        data.putInt("code", code);
        data.putString("packageName", packageName);
        data.putInt("uid", uid);
        msg.setData(data);
        msg.obj = op;
        mHandler.sendMessage(msg);
        Binder.restoreCallingIdentity(origId);
        return result;
    }

    @Override
    @Override
    public int checkOperation(int code, int uid, String packageName) {
    public int checkOperation(int code, int uid, String packageName) {
        boolean strict;
        verifyIncomingUid(uid);
        verifyIncomingUid(uid);
        verifyIncomingOp(code);
        verifyIncomingOp(code);
        synchronized (this) {
        synchronized (this) {
            Op op = getOpLocked(AppOpsManager.opToSwitch(code), uid, packageName, false);
            Op op = getOpLocked(AppOpsManager.opToSwitch(code), uid, packageName, false);
            if (op == null) {
            if (op == null) {
                if (!isStrict(code, uid, packageName)) {
                    return AppOpsManager.MODE_ALLOWED;
                    return AppOpsManager.MODE_ALLOWED;
                } else {
                    return  AppOpsManager.MODE_ASK;
                }
            }
            }
            return op.mode;
            return op.mode;
        }
        }
@@ -496,67 +660,83 @@ public class AppOpsService extends IAppOpsService.Stub {


    @Override
    @Override
    public int noteOperation(int code, int uid, String packageName) {
    public int noteOperation(int code, int uid, String packageName) {
        int mode;
        Ops ops;
        Op op;
        final Op switchOp;
        final int switchCode;
        final Result res;
        verifyIncomingUid(uid);
        verifyIncomingUid(uid);
        verifyIncomingOp(code);
        verifyIncomingOp(code);
        synchronized (this) {
        synchronized (this) {
            Ops ops = getOpsLocked(uid, packageName, true);
            ops = getOpsLocked(uid, packageName, true);
            if (ops == null) {
            if (ops == null) {
                if (DEBUG) Log.d(TAG, "noteOperation: no op for code " + code + " uid " + uid
                if (DEBUG) Log.d(TAG, "noteOperation: no op for code " + code + " uid " + uid
                        + " package " + packageName);
                        + " package " + packageName);
                return AppOpsManager.MODE_IGNORED;
                return AppOpsManager.MODE_IGNORED;
            }
            }
            Op op = getOpLocked(ops, code, true);

            boolean strict = isStrict(code, uid, packageName);
            op = getOpLocked(ops, uid, code, true, strict);
            if (op.duration == -1) {
            if (op.duration == -1) {
                Slog.w(TAG, "Noting op not finished: uid " + uid + " pkg " + packageName
                Slog.w(TAG, "Noting op not finished: uid " + uid + " pkg " + packageName
                        + " code " + code + " time=" + op.time + " duration=" + op.duration);
                        + " code " + code + " time=" + op.time + " duration=" + op.duration);
            }
            }
            op.duration = 0;
            op.duration = 0;
            final int switchCode = AppOpsManager.opToSwitch(code);
            switchCode = AppOpsManager.opToSwitch(code);
            final Op switchOp = switchCode != code ? getOpLocked(ops, switchCode, true) : op;
            switchOp = switchCode != code ? getOpLocked(ops, uid, switchCode, true, strict) : op;
            if (switchOp.mode != AppOpsManager.MODE_ALLOWED) {
            mode = switchOp.mode;
                if (DEBUG) Log.d(TAG, "noteOperation: reject #" + op.mode + " for code "
            if (mode != AppOpsManager.MODE_ASK) {
                        + switchCode + " (" + code + ") uid " + uid + " package " + packageName);
                recordOperationLocked(code, uid, packageName, switchOp.mode);
                op.rejectTime = System.currentTimeMillis();
                return switchOp.mode;
                return switchOp.mode;
            } else {
                res = askOperationLocked(code, uid, packageName, switchOp);
            }
            }
            if (DEBUG) Log.d(TAG, "noteOperation: allowing code " + code + " uid " + uid
                    + " package " + packageName);
            op.time = System.currentTimeMillis();
            op.rejectTime = 0;
            return AppOpsManager.MODE_ALLOWED;
        }
        }

        return res.get();
    }
    }


    @Override
    @Override
    public int startOperation(int code, int uid, String packageName) {
    public int startOperation(int code, int uid, String packageName) {
        int mode;
        Ops ops;
        Op op;
        final Op switchOp;
        final int switchCode;
        final Result res;
        verifyIncomingUid(uid);
        verifyIncomingUid(uid);
        verifyIncomingOp(code);
        verifyIncomingOp(code);
        synchronized (this) {
        synchronized (this) {
            Ops ops = getOpsLocked(uid, packageName, true);
            ops = getOpsLocked(uid, packageName, true);
            if (ops == null) {
            if (ops == null) {
                if (DEBUG) Log.d(TAG, "startOperation: no op for code " + code + " uid " + uid
                if (DEBUG) Log.d(TAG, "startOperation: no op for code " + code + " uid " + uid
                        + " package " + packageName);
                        + " package " + packageName);
                return AppOpsManager.MODE_IGNORED;
                return AppOpsManager.MODE_IGNORED;
            }
            }
            Op op = getOpLocked(ops, code, true);
            boolean strict = isStrict(code, uid, packageName);
            final int switchCode = AppOpsManager.opToSwitch(code);
            op = getOpLocked(ops, uid, code, true, strict);
            final Op switchOp = switchCode != code ? getOpLocked(ops, switchCode, true) : op;
            switchCode = AppOpsManager.opToSwitch(code);
            if (switchOp.mode != AppOpsManager.MODE_ALLOWED) {
            switchOp = switchCode != code ? getOpLocked(ops, uid, switchCode, true, strict) : op;
                if (DEBUG) Log.d(TAG, "startOperation: reject #" + op.mode + " for code "
            mode = switchOp.mode;
                        + switchCode + " (" + code + ") uid " + uid + " package " + packageName);
            if (mode != AppOpsManager.MODE_ASK) {
                op.rejectTime = System.currentTimeMillis();
                recordOperationLocked(code, uid, packageName, switchOp.mode);
                return switchOp.mode;
                if (mode == AppOpsManager.MODE_ALLOWED) {
            }
            if (DEBUG) Log.d(TAG, "startOperation: allowing code " + code + " uid " + uid
                    + " package " + packageName);
                    if (op.nesting == 0) {
                    if (op.nesting == 0) {
                        op.time = System.currentTimeMillis();
                        op.time = System.currentTimeMillis();
                        op.rejectTime = 0;
                        op.rejectTime = 0;
                        op.duration = -1;
                        op.duration = -1;
                    }
                    }
                    op.nesting++;
                    op.nesting++;
            return AppOpsManager.MODE_ALLOWED;
                }
                }
                return switchOp.mode;
            } else {
                op.tempNesting++;
                res = askOperationLocked(code, uid, packageName, switchOp);
            }
        }

        return res.get();
    }
    }


    @Override
    @Override
@@ -669,16 +849,17 @@ public class AppOpsService extends IAppOpsService.Stub {
        if (ops == null) {
        if (ops == null) {
            return null;
            return null;
        }
        }
        return getOpLocked(ops, code, edit);
        return getOpLocked(ops, uid, code, edit, isStrict(code, uid, packageName));
    }
    }


    private Op getOpLocked(Ops ops, int code, boolean edit) {
    private Op getOpLocked(Ops ops, int uid, int code, boolean edit, boolean strict) {
        Op op = ops.get(code);
        Op op = ops.get(code);
        if (op == null) {
        if (op == null) {
            if (!edit) {
            if (!edit) {
                return null;
                return null;
            }
            }
            op = new Op(code);

            op = new Op(code, strict);
            ops.put(code, op);
            ops.put(code, op);
        }
        }
        if (edit) {
        if (edit) {
@@ -788,7 +969,9 @@ public class AppOpsService extends IAppOpsService.Stub {


            String tagName = parser.getName();
            String tagName = parser.getName();
            if (tagName.equals("op")) {
            if (tagName.equals("op")) {
                Op op = new Op(Integer.parseInt(parser.getAttributeValue(null, "n")));
                int code = Integer.parseInt(parser.getAttributeValue(null, "n"));
                boolean strict = isStrict(code, uid, pkgName);
                Op op = new Op(code, strict);
                String mode = parser.getAttributeValue(null, "m");
                String mode = parser.getAttributeValue(null, "m");
                if (mode != null) {
                if (mode != null) {
                    op.mode = Integer.parseInt(mode);
                    op.mode = Integer.parseInt(mode);
@@ -861,9 +1044,7 @@ public class AppOpsService extends IAppOpsService.Stub {
                            AppOpsManager.OpEntry op = ops.get(j);
                            AppOpsManager.OpEntry op = ops.get(j);
                            out.startTag(null, "op");
                            out.startTag(null, "op");
                            out.attribute(null, "n", Integer.toString(op.getOp()));
                            out.attribute(null, "n", Integer.toString(op.getOp()));
                            if (op.getMode() != AppOpsManager.MODE_ALLOWED) {
                            out.attribute(null, "m", Integer.toString(op.getMode()));
                            out.attribute(null, "m", Integer.toString(op.getMode()));
                            }
                            long time = op.getTime();
                            long time = op.getTime();
                            if (time != 0) {
                            if (time != 0) {
                                out.attribute(null, "t", Long.toString(time));
                                out.attribute(null, "t", Long.toString(time));
Loading