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

Commit a06de0f2 authored by Dianne Hackborn's avatar Dianne Hackborn
Browse files

New "app ops" service.

Initial implementation, tracking use of the vibrator, GPS,
and location reports.

Also includes an update to battery stats to also keep track of
vibrator usage (since I had to be in the vibrator code anyway
to instrument it).

The service itself is only half-done.  Currently no API to
retrieve the data (which once there will allow us to show you
which apps are currently causing the GPS to run and who has
recently accessed your location), it doesn't persist its data
like it should, and no way to tell it to reject app requests
for various operations.

But hey, it's a start!

Change-Id: I05b8d76cc4a4f7f37bc758c1701f51f9e0550e15
parent 2e9f65f9
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -166,6 +166,7 @@ LOCAL_SRC_FILES += \
	core/java/android/speech/IRecognitionService.aidl \
	core/java/android/speech/tts/ITextToSpeechCallback.aidl \
	core/java/android/speech/tts/ITextToSpeechService.aidl \
	core/java/com/android/internal/app/IAppOpsService.aidl \
	core/java/com/android/internal/app/IBatteryStats.aidl \
	core/java/com/android/internal/app/IUsageStats.aidl \
	core/java/com/android/internal/app/IMediaContainerService.aidl \
+110 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 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.
 */

package android.app;

import com.android.internal.app.IAppOpsService;

import android.content.Context;
import android.os.Process;
import android.os.RemoteException;

/** @hide */
public class AppOpsManager {
    final Context mContext;
    final IAppOpsService mService;

    public static final int MODE_ALLOWED = 0;
    public static final int MODE_IGNORED = 1;
    public static final int MODE_ERRORED = 2;

    public static final int OP_LOCATION = 0;
    public static final int OP_GPS = 1;
    public static final int OP_VIBRATE = 2;

    public static String opToString(int op) {
        switch (op) {
            case OP_LOCATION: return "LOCATION";
            case OP_GPS: return "GPS";
            case OP_VIBRATE: return "VIBRATE";
            default: return "Unknown(" + op + ")";
        }
    }

    public AppOpsManager(Context context, IAppOpsService service) {
        mContext = context;
        mService = service;
    }

    public int noteOp(int op, int uid, String packageName) {
        try {
            int mode = mService.noteOperation(op, uid, packageName);
            if (mode == MODE_ERRORED) {
                throw new SecurityException("Operation not allowed");
            }
            return mode;
        } catch (RemoteException e) {
        }
        return MODE_IGNORED;
    }

    public int noteOpNoThrow(int op, int uid, String packageName) {
        try {
            return mService.noteOperation(op, uid, packageName);
        } catch (RemoteException e) {
        }
        return MODE_IGNORED;
    }

    public int noteOp(int op) {
        return noteOp(op, Process.myUid(), mContext.getPackageName());
    }

    public int startOp(int op, int uid, String packageName) {
        try {
            int mode = mService.startOperation(op, uid, packageName);
            if (mode == MODE_ERRORED) {
                throw new SecurityException("Operation not allowed");
            }
            return mode;
        } catch (RemoteException e) {
        }
        return MODE_IGNORED;
    }

    public int startOpNoThrow(int op, int uid, String packageName) {
        try {
            return mService.startOperation(op, uid, packageName);
        } catch (RemoteException e) {
        }
        return MODE_IGNORED;
    }

    public int startOp(int op) {
        return startOp(op, Process.myUid(), mContext.getPackageName());
    }

    public void finishOp(int op, int uid, String packageName) {
        try {
            mService.finishOperation(op, uid, packageName);
        } catch (RemoteException e) {
        }
    }

    public void finishOp(int op) {
        finishOp(op, Process.myUid(), mContext.getPackageName());
    }
}
+15 −0
Original line number Diff line number Diff line
@@ -141,6 +141,21 @@ final class ApplicationPackageManager extends PackageManager {
        throw new NameNotFoundException(packageName);
    }

    @Override
    public int getPackageUid(String packageName, int userHandle)
            throws NameNotFoundException {
        try {
            int uid = mPM.getPackageUid(packageName, userHandle);
            if (uid >= 0) {
                return uid;
            }
        } catch (RemoteException e) {
            throw new RuntimeException("Package manager has died", e);
        }

        throw new NameNotFoundException(packageName);
    }

    @Override
    public PermissionInfo getPermissionInfo(String name, int flags)
            throws NameNotFoundException {
+11 −4
Original line number Diff line number Diff line
@@ -47,11 +47,9 @@ import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
import android.hardware.ISerialManager;
import android.hardware.SensorManager;
import android.hardware.SerialManager;
import android.hardware.SystemSensorManager;
import android.hardware.display.DisplayManager;
import android.hardware.input.IInputManager;
import android.hardware.input.InputManager;
import android.hardware.usb.IUsbManager;
import android.hardware.usb.UsbManager;
@@ -109,6 +107,8 @@ import android.view.textservice.TextServicesManager;
import android.accounts.AccountManager;
import android.accounts.IAccountManager;
import android.app.admin.DevicePolicyManager;

import com.android.internal.app.IAppOpsService;
import com.android.internal.os.IDropBoxManagerService;

import java.io.File;
@@ -499,7 +499,7 @@ class ContextImpl extends Context {

        registerService(VIBRATOR_SERVICE, new ServiceFetcher() {
                public Object createService(ContextImpl ctx) {
                    return new SystemVibrator();
                    return new SystemVibrator(ctx);
                }});

        registerService(WALLPAPER_SERVICE, WALLPAPER_FETCHER);
@@ -530,11 +530,18 @@ class ContextImpl extends Context {
                }});

        registerService(USER_SERVICE, new ServiceFetcher() {
            public Object getService(ContextImpl ctx) {
            public Object createService(ContextImpl ctx) {
                IBinder b = ServiceManager.getService(USER_SERVICE);
                IUserManager service = IUserManager.Stub.asInterface(b);
                return new UserManager(ctx, service);
            }});

        registerService(APP_OPS_SERVICE, new ServiceFetcher() {
            public Object createService(ContextImpl ctx) {
                IBinder b = ServiceManager.getService(APP_OPS_SERVICE);
                IAppOpsService service = IAppOpsService.Stub.asInterface(b);
                return new AppOpsManager(ctx, service);
            }});
    }

    static ContextImpl getImpl(Context context) {
+12 −0
Original line number Diff line number Diff line
@@ -2288,6 +2288,18 @@ public abstract class Context {
     */
    public static final String USER_SERVICE = "user";

    /**
     * Use with {@link #getSystemService} to retrieve a
     * {@link android.app.AppOpsManager} for tracking application operations
     * on the device.
     *
     * @see #getSystemService
     * @see android.app.AppOpsManager
     *
     * @hide
     */
    public static final String APP_OPS_SERVICE = "appops";

    /**
     * Determine whether the given permission is allowed for a particular
     * process and user ID running in the system.
Loading