am 107cd552: am 17daa3d0: am 574f5379: Merge "Add body sensors app op - framework base" into mnc-dev

* commit '107cd552f1d88ae22fde0284f4a64f78eaadfbc1':
  Add body sensors app op - framework base
This commit is contained in:
Svet Ganov
2015-05-01 23:45:22 +00:00
committed by Android Git Automerger
11 changed files with 175 additions and 121 deletions

View File

@@ -223,8 +223,10 @@ public class AppOpsManager {
public static final int OP_PROCESS_OUTGOING_CALLS = 54;
/** @hide User the fingerprint API. */
public static final int OP_USE_FINGERPRINT = 55;
/** @hide Access to body sensors such as heart rate, etc. */
public static final int OP_BODY_SENSORS = 56;
/** @hide */
public static final int _NUM_OP = 56;
public static final int _NUM_OP = 57;
/** Access to coarse location information. */
public static final String OPSTR_COARSE_LOCATION = "android:coarse_location";
@@ -280,9 +282,6 @@ public class AppOpsManager {
/** @hide Allows an application to send SMS messages. */
public static final String OPSTR_SEND_SMS
= "android:send_sms";
/** @hide Allows an application to add system alert windows. */
public static final String OPSTR_SYSTEM_ALERT_WINDOW
= "android:system_alert_window";
/** @hide Required to be able to access the camera device. */
public static final String OPSTR_CAMERA
= "android:camera";
@@ -295,6 +294,15 @@ public class AppOpsManager {
/** @hide Required to access phone state related information. */
public static final String OPSTR_ADD_VOICEMAIL
= "android:add_voicemail";
/** @hide Access APIs for SIP calling over VOIP or WiFi */
public static final String OPSTR_USE_SIP
= "android:use_sip";
/** @hide Use the fingerprint API. */
public static final String OPSTR_USE_FINGERPRINT
= "android:use_fingerprint";
/** @hide Access to body sensors such as heart rate, etc. */
public static final String OPSTR_BODY_SENSORS
= "android:body_sensors";
/**
* This maps each operation to the operation that serves as the
@@ -360,7 +368,8 @@ public class AppOpsManager {
OP_ADD_VOICEMAIL,
OP_USE_SIP,
OP_PROCESS_OUTGOING_CALLS,
OP_USE_FINGERPRINT
OP_USE_FINGERPRINT,
OP_BODY_SENSORS
};
/**
@@ -372,30 +381,30 @@ public class AppOpsManager {
OPSTR_FINE_LOCATION,
null,
null,
OPSTR_READ_CONTACTS,
OPSTR_WRITE_CONTACTS,
OPSTR_READ_CALL_LOG,
OPSTR_WRITE_CALL_LOG,
OPSTR_READ_CALENDAR,
OPSTR_WRITE_CALENDAR,
null,
null,
null,
OPSTR_CALL_PHONE,
OPSTR_READ_SMS,
null,
OPSTR_RECEIVE_SMS,
null,
OPSTR_RECEIVE_MMS,
OPSTR_RECEIVE_WAP_PUSH,
OPSTR_SEND_SMS,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
OPSTR_CAMERA,
OPSTR_RECORD_AUDIO,
null,
null,
null,
@@ -419,11 +428,12 @@ public class AppOpsManager {
null,
null,
null,
OPSTR_READ_PHONE_STATE,
OPSTR_ADD_VOICEMAIL,
OPSTR_USE_SIP,
null,
null,
null,
null,
null
OPSTR_USE_FINGERPRINT,
OPSTR_BODY_SENSORS
};
/**
@@ -486,7 +496,8 @@ public class AppOpsManager {
"ADD_VOICEMAIL",
"USE_SIP",
"PROCESS_OUTGOING_CALLS",
"USE_FINGERPRINT"
"USE_FINGERPRINT",
"BODY_SENSORS"
};
/**
@@ -549,7 +560,8 @@ public class AppOpsManager {
Manifest.permission.ADD_VOICEMAIL,
Manifest.permission.USE_SIP,
Manifest.permission.PROCESS_OUTGOING_CALLS,
Manifest.permission.USE_FINGERPRINT
Manifest.permission.USE_FINGERPRINT,
Manifest.permission.BODY_SENSORS
};
/**
@@ -613,7 +625,8 @@ public class AppOpsManager {
null, // ADD_VOICEMAIL
null, // USE_SIP
null, // PROCESS_OUTGOING_CALLS
null // USE_FINGERPRINT
null, // USE_FINGERPRINT
null // BODY_SENSORS
};
/**
@@ -676,7 +689,8 @@ public class AppOpsManager {
false, //ADD_VOICEMAIL
false, // USE_SIP
false, // PROCESS_OUTGOING_CALLS
false // USE_FINGERPRINT
false, // USE_FINGERPRINT
false // BODY_SENSORS
};
/**
@@ -738,6 +752,7 @@ public class AppOpsManager {
AppOpsManager.MODE_ALLOWED,
AppOpsManager.MODE_ALLOWED,
AppOpsManager.MODE_ALLOWED,
AppOpsManager.MODE_ALLOWED,
AppOpsManager.MODE_ALLOWED
};
@@ -804,37 +819,19 @@ public class AppOpsManager {
false,
false,
false,
false,
false
};
/**
* This is a mapping from a permission name to public app op name.
* Mapping from an app op name to the app op code.
*/
private static final ArrayMap<String, String> sPermToOp = new ArrayMap<>();
static {
sPermToOp.put(Manifest.permission.ACCESS_COARSE_LOCATION, OPSTR_COARSE_LOCATION);
sPermToOp.put(Manifest.permission.ACCESS_FINE_LOCATION, OPSTR_FINE_LOCATION);
sPermToOp.put(Manifest.permission.PACKAGE_USAGE_STATS, OPSTR_GET_USAGE_STATS);
sPermToOp.put(Manifest.permission.READ_CONTACTS, OPSTR_READ_CONTACTS);
sPermToOp.put(Manifest.permission.WRITE_CONTACTS, OPSTR_WRITE_CONTACTS);
sPermToOp.put(Manifest.permission.READ_CALL_LOG, OPSTR_READ_CALL_LOG);
sPermToOp.put(Manifest.permission.WRITE_CALL_LOG, OPSTR_WRITE_CALL_LOG);
sPermToOp.put(Manifest.permission.READ_CALENDAR, OPSTR_READ_CALENDAR);
sPermToOp.put(Manifest.permission.WRITE_CALENDAR, OPSTR_WRITE_CALENDAR);
sPermToOp.put(Manifest.permission.CALL_PHONE, OPSTR_CALL_PHONE);
sPermToOp.put(Manifest.permission.READ_SMS, OPSTR_READ_SMS);
sPermToOp.put(Manifest.permission.RECEIVE_SMS, OPSTR_RECEIVE_SMS);
sPermToOp.put(Manifest.permission.RECEIVE_MMS, OPSTR_RECEIVE_MMS);
sPermToOp.put(Manifest.permission.RECEIVE_WAP_PUSH, OPSTR_RECEIVE_WAP_PUSH);
sPermToOp.put(Manifest.permission.SEND_SMS, OPSTR_SEND_SMS);
sPermToOp.put(Manifest.permission.SYSTEM_ALERT_WINDOW, OPSTR_SYSTEM_ALERT_WINDOW);
sPermToOp.put(Manifest.permission.CAMERA, OPSTR_CAMERA);
sPermToOp.put(Manifest.permission.RECORD_AUDIO, OPSTR_RECORD_AUDIO);
sPermToOp.put(Manifest.permission.READ_PHONE_STATE, OPSTR_READ_PHONE_STATE);
sPermToOp.put(Manifest.permission.ADD_VOICEMAIL, OPSTR_ADD_VOICEMAIL);
}
private static HashMap<String, Integer> sOpStrToOp = new HashMap<>();
private static HashMap<String, Integer> sOpStrToOp = new HashMap<String, Integer>();
/**
* Mapping from a permission to the corresponding app op.
*/
private static HashMap<String, Integer> sPermToOp = new HashMap<>();
static {
if (sOpToSwitch.length != _NUM_OP) {
@@ -874,6 +871,11 @@ public class AppOpsManager {
sOpStrToOp.put(sOpToString[i], i);
}
}
for (int i=0; i<_NUM_OP; i++) {
if (sOpPerms[i] != null) {
sPermToOp.put(sOpPerms[i], i);
}
}
}
/**
@@ -921,6 +923,14 @@ public class AppOpsManager {
return sOpRestrictions[op];
}
/**
* Retrieve the app op code for a permission, or null if there is not one.
* @hide
*/
public static int permissionToOpCode(String permission) {
return sPermToOp.get(permission);
}
/**
* Retrieve whether the op allows the system (and system ui) to
* bypass the user restriction.
@@ -1185,7 +1195,11 @@ public class AppOpsManager {
*/
@SystemApi
public static String permissionToOp(String permission) {
return sPermToOp.get(permission);
final Integer opCode = sPermToOp.get(permission);
if (opCode == null) {
return null;
}
return sOpToString[opCode];
}
/**

View File

@@ -41,16 +41,19 @@ import java.util.List;
*/
public class SystemSensorManager extends SensorManager {
private static native void nativeClassInit();
private static native int nativeGetNextSensor(Sensor sensor, int next);
private static native int nativeEnableDataInjection(boolean enable);
private static native long nativeCreate(String opPackageName);
private static native int nativeGetNextSensor(long nativeInstance, Sensor sensor, int next);
private static native int nativeEnableDataInjection(long nativeInstance, boolean enable);
private static boolean sSensorModuleInitialized = false;
private static final Object sSensorModuleLock = new Object();
private static final ArrayList<Sensor> sFullSensorsList = new ArrayList<Sensor>();
private static final SparseArray<Sensor> sHandleToSensor = new SparseArray<Sensor>();
private static InjectEventQueue mInjectEventQueue = null;
private static boolean mDataInjectionMode = false;
private final Object mLock = new Object();
private final ArrayList<Sensor> mFullSensorsList = new ArrayList<>();
private final SparseArray<Sensor> mHandleToSensor = new SparseArray<>();
// Listener list
private final HashMap<SensorEventListener, SensorEventQueue> mSensorListeners =
new HashMap<SensorEventListener, SensorEventQueue>();
@@ -60,44 +63,44 @@ public class SystemSensorManager extends SensorManager {
// Looper associated with the context in which this instance was created.
private final Looper mMainLooper;
private final int mTargetSdkLevel;
private final String mPackageName;
private final Context mContext;
private final boolean mHasDataInjectionPermissions;
private final long mNativeInstance;
/** {@hide} */
public SystemSensorManager(Context context, Looper mainLooper) {
mMainLooper = mainLooper;
mTargetSdkLevel = context.getApplicationInfo().targetSdkVersion;
mPackageName = context.getPackageName();
synchronized(sSensorModuleLock) {
mContext = context;
mNativeInstance = nativeCreate(context.getOpPackageName());
synchronized(mLock) {
if (!sSensorModuleInitialized) {
sSensorModuleInitialized = true;
nativeClassInit();
// initialize the sensor list
final ArrayList<Sensor> fullList = sFullSensorsList;
int i = 0;
do {
Sensor sensor = new Sensor();
i = nativeGetNextSensor(sensor, i);
if (i>=0) {
//Log.d(TAG, "found sensor: " + sensor.getName() +
// ", handle=" + sensor.getHandle());
fullList.add(sensor);
sHandleToSensor.append(sensor.getHandle(), sensor);
}
} while (i>0);
}
mHasDataInjectionPermissions = context.checkSelfPermission(
Manifest.permission.HARDWARE_TEST) == PackageManager.PERMISSION_GRANTED;
}
// initialize the sensor list
int i = 0;
while(true) {
Sensor sensor = new Sensor();
i = nativeGetNextSensor(mNativeInstance, sensor, i);
if (i <= 0) {
break;
}
mFullSensorsList.add(sensor);
mHandleToSensor.append(sensor.getHandle(), sensor);
}
}
/** @hide */
@Override
protected List<Sensor> getFullSensorList() {
return sFullSensorsList;
return mFullSensorsList;
}
@@ -232,8 +235,8 @@ public class SystemSensorManager extends SensorManager {
throw new SecurityException("Permission denial. Calling enableDataInjection without "
+ Manifest.permission.HARDWARE_TEST);
}
synchronized (sSensorModuleLock) {
int ret = nativeEnableDataInjection(enable);
synchronized (mLock) {
int ret = nativeEnableDataInjection(mNativeInstance, enable);
// The HAL does not support injection. Ignore.
if (ret != 0) {
Log.e(TAG, "HAL does not support data injection");
@@ -255,7 +258,7 @@ public class SystemSensorManager extends SensorManager {
throw new SecurityException("Permission denial. Calling injectSensorData without "
+ Manifest.permission.HARDWARE_TEST);
}
synchronized (sSensorModuleLock) {
synchronized (mLock) {
if (!mDataInjectionMode) {
Log.e(TAG, "Data injection mode not activated before calling injectSensorData");
return false;
@@ -284,15 +287,17 @@ public class SystemSensorManager extends SensorManager {
* SensorManager instance.
*/
private static abstract class BaseEventQueue {
private native long nativeInitBaseEventQueue(WeakReference<BaseEventQueue> eventQWeak,
MessageQueue msgQ, float[] scratch, String packageName, int mode);
private static native long nativeInitBaseEventQueue(long nativeManager,
WeakReference<BaseEventQueue> eventQWeak, MessageQueue msgQ, float[] scratch,
String packageName, int mode, String opPackageName);
private static native int nativeEnableSensor(long eventQ, int handle, int rateUs,
int maxBatchReportLatencyUs);
private static native int nativeDisableSensor(long eventQ, int handle);
private static native void nativeDestroySensorEventQueue(long eventQ);
private static native int nativeFlushSensor(long eventQ);
private static native int nativeInjectSensorData(long eventQ, int handle,
float[] values,int accuracy, long timestamp);
float[] values,int accuracy, long timestamp);
private long nSensorEventQueue;
private final SparseBooleanArray mActiveSensors = new SparseBooleanArray();
protected final SparseIntArray mSensorAccuracies = new SparseIntArray();
@@ -305,8 +310,9 @@ public class SystemSensorManager extends SensorManager {
protected static final int OPERATING_MODE_DATA_INJECTION = 1;
BaseEventQueue(Looper looper, SystemSensorManager manager, int mode) {
nSensorEventQueue = nativeInitBaseEventQueue(new WeakReference<BaseEventQueue>(this),
looper.getQueue(), mScratch, manager.mPackageName, mode);
nSensorEventQueue = nativeInitBaseEventQueue(manager.mNativeInstance,
new WeakReference<>(this), looper.getQueue(), mScratch,
manager.mContext.getPackageName(), mode, manager.mContext.getOpPackageName());
mCloseGuard.open("dispose");
mManager = manager;
}
@@ -339,7 +345,7 @@ public class SystemSensorManager extends SensorManager {
for (int i=0 ; i<mActiveSensors.size(); i++) {
if (mActiveSensors.valueAt(i) == true) {
int handle = mActiveSensors.keyAt(i);
Sensor sensor = sHandleToSensor.get(handle);
Sensor sensor = mManager.mHandleToSensor.get(handle);
if (sensor != null) {
disableSensor(sensor);
mActiveSensors.put(handle, false);
@@ -452,7 +458,7 @@ public class SystemSensorManager extends SensorManager {
@Override
protected void dispatchSensorEvent(int handle, float[] values, int inAccuracy,
long timestamp) {
final Sensor sensor = sHandleToSensor.get(handle);
final Sensor sensor = mManager.mHandleToSensor.get(handle);
SensorEvent t = null;
synchronized (mSensorsEvents) {
t = mSensorsEvents.get(handle);
@@ -481,7 +487,7 @@ public class SystemSensorManager extends SensorManager {
@SuppressWarnings("unused")
protected void dispatchFlushCompleteEvent(int handle) {
if (mListener instanceof SensorEventListener2) {
final Sensor sensor = sHandleToSensor.get(handle);
final Sensor sensor = mManager.mHandleToSensor.get(handle);
((SensorEventListener2)mListener).onFlushCompleted(sensor);
}
return;
@@ -519,7 +525,7 @@ public class SystemSensorManager extends SensorManager {
@Override
protected void dispatchSensorEvent(int handle, float[] values, int accuracy,
long timestamp) {
final Sensor sensor = sHandleToSensor.get(handle);
final Sensor sensor = mManager.mHandleToSensor.get(handle);
TriggerEvent t = null;
synchronized (mTriggerEvents) {
t = mTriggerEvents.get(handle);
@@ -546,7 +552,7 @@ public class SystemSensorManager extends SensorManager {
}
}
static final class InjectEventQueue extends BaseEventQueue {
final class InjectEventQueue extends BaseEventQueue {
public InjectEventQueue(Looper looper, SystemSensorManager manager) {
super(looper, manager, OPERATING_MODE_DATA_INJECTION);
}

View File

@@ -21,4 +21,5 @@ package android.os;
interface IPermissionController {
boolean checkPermission(String permission, int pid, int uid);
String[] getPackagesForUid(int uid);
boolean isRuntimePermission(String permission);
}

View File

@@ -30,6 +30,7 @@ interface IAppOpsService {
void startWatchingMode(int op, String packageName, IAppOpsCallback callback);
void stopWatchingMode(IAppOpsCallback callback);
IBinder getToken(IBinder clientToken);
int permissionToOpCode(String permission);
// Remaining methods are only used in Java.
int checkPackage(int uid, String packageName);
@@ -42,5 +43,4 @@ interface IAppOpsService {
void setUserRestrictions(in Bundle restrictions, int userHandle);
void removeUser(int userHandle);
}

View File

@@ -134,13 +134,21 @@ getInternedString(JNIEnv *env, const String8* string) {
return internedString;
}
static jint
nativeGetNextSensor(JNIEnv *env, jclass clazz, jobject sensor, jint next)
static jlong
nativeCreate
(JNIEnv *env, jclass clazz, jstring opPackageName)
{
SensorManager& mgr(SensorManager::getInstance());
ScopedUtfChars opPackageNameUtf(env, opPackageName);
return (jlong) new SensorManager(String16(opPackageNameUtf.c_str()));
}
static jint
nativeGetNextSensor(JNIEnv *env, jclass clazz, jlong sensorManager, jobject sensor, jint next)
{
SensorManager* mgr = reinterpret_cast<SensorManager*>(sensorManager);
Sensor const* const* sensorList;
size_t count = mgr.getSensorList(&sensorList);
size_t count = mgr->getSensorList(&sensorList);
if (size_t(next) >= count) {
return -1;
}
@@ -174,9 +182,10 @@ nativeGetNextSensor(JNIEnv *env, jclass clazz, jobject sensor, jint next)
return size_t(next) < count ? next : 0;
}
static int nativeEnableDataInjection(JNIEnv *_env, jclass _this, jboolean enable) {
SensorManager& mgr(SensorManager::getInstance());
return mgr.enableDataInjection(enable);
static int nativeEnableDataInjection(JNIEnv *_env, jclass _this, jlong sensorManager,
jboolean enable) {
SensorManager* mgr = reinterpret_cast<SensorManager*>(sensorManager);
return mgr->enableDataInjection(enable);
}
//----------------------------------------------------------------------------
@@ -281,12 +290,12 @@ private:
}
};
static jlong nativeInitSensorEventQueue(JNIEnv *env, jclass clazz, jobject eventQWeak, jobject msgQ,
jfloatArray scratch, jstring packageName, jint mode) {
SensorManager& mgr(SensorManager::getInstance());
static jlong nativeInitSensorEventQueue(JNIEnv *env, jclass clazz, jlong sensorManager,
jobject eventQWeak, jobject msgQ, jfloatArray scratch, jstring packageName, jint mode) {
SensorManager* mgr = reinterpret_cast<SensorManager*>(sensorManager);
ScopedUtfChars packageUtf(env, packageName);
String8 clientName(packageUtf.c_str());
sp<SensorEventQueue> queue(mgr.createEventQueue(clientName, mode));
sp<SensorEventQueue> queue(mgr->createEventQueue(clientName, mode));
sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, msgQ);
if (messageQueue == NULL) {
@@ -339,20 +348,23 @@ static JNINativeMethod gSystemSensorManagerMethods[] = {
{"nativeClassInit",
"()V",
(void*)nativeClassInit },
{"nativeCreate",
"(Ljava/lang/String;)J",
(void*)nativeCreate },
{"nativeGetNextSensor",
"(Landroid/hardware/Sensor;I)I",
"(JLandroid/hardware/Sensor;I)I",
(void*)nativeGetNextSensor },
{"nativeEnableDataInjection",
"(Z)I",
"(JZ)I",
(void*)nativeEnableDataInjection },
};
static JNINativeMethod gBaseEventQueueMethods[] = {
{"nativeInitBaseEventQueue",
"(Ljava/lang/ref/WeakReference;Landroid/os/MessageQueue;[FLjava/lang/String;I)J",
(void*)nativeInitSensorEventQueue },
"(JLjava/lang/ref/WeakReference;Landroid/os/MessageQueue;[FLjava/lang/String;ILjava/lang/String;)J",
(void*)nativeInitSensorEventQueue },
{"nativeEnableSensor",
"(JIII)I",

View File

@@ -38,11 +38,6 @@ using android::String8;
/*****************************************************************************/
ASensorManager* ASensorManager_getInstance()
{
return &SensorManager::getInstance();
}
int ASensorManager_getSensorList(ASensorManager* manager,
ASensorList* list)
{

View File

@@ -744,6 +744,11 @@ public class AppOpsService extends IAppOpsService.Stub {
}
}
@Override
public int permissionToOpCode(String permission) {
return AppOpsManager.permissionToOpCode(permission);
}
void finishOperationLocked(Op op) {
if (op.nesting <= 1) {
if (op.nesting == 1) {

View File

@@ -47,6 +47,7 @@ import android.app.ProfilerInfo;
import android.app.usage.UsageEvents;
import android.app.usage.UsageStatsManagerInternal;
import android.appwidget.AppWidgetManager;
import android.content.pm.PermissionInfo;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Point;
@@ -6619,6 +6620,18 @@ public final class ActivityManagerService extends ActivityManagerNative
return mActivityManagerService.mContext.getPackageManager()
.getPackagesForUid(uid);
}
@Override
public boolean isRuntimePermission(String permission) {
try {
PermissionInfo info = mActivityManagerService.mContext.getPackageManager()
.getPermissionInfo(permission, 0);
return info.protectionLevel == PermissionInfo.PROTECTION_DANGEROUS;
} catch (NameNotFoundException nnfe) {
Slog.e(TAG, "No such permission: "+ permission, nnfe);
}
return false;
}
}
class IntentFirewallInterface implements IntentFirewall.AMSInterface {

View File

@@ -25,7 +25,7 @@
namespace android {
static void android_server_SystemServer_nativeInit(JNIEnv* /* env */, jobject /* clazz */) {
static void android_server_SystemServer_startSensorService(JNIEnv* /* env */, jobject /* clazz */) {
char propBuf[PROPERTY_VALUE_MAX];
property_get("system_init.startsensorservice", propBuf, "1");
if (strcmp(propBuf, "1") == 0) {
@@ -39,7 +39,7 @@ static void android_server_SystemServer_nativeInit(JNIEnv* /* env */, jobject /*
*/
static JNINativeMethod gMethods[] = {
/* name, signature, funcPtr */
{ "nativeInit", "()V", (void*) android_server_SystemServer_nativeInit },
{ "startSensorService", "()V", (void*) android_server_SystemServer_startSensorService },
};
int register_android_server_SystemServer(JNIEnv* env)

View File

@@ -156,9 +156,9 @@ public final class SystemServer {
private boolean mFirstBoot;
/**
* Called to initialize native system services.
* Start the sensor service.
*/
private static native void nativeInit();
private static native void startSensorService();
/**
* The main entry point from zygote.
@@ -233,7 +233,6 @@ public final class SystemServer {
// Initialize native services.
System.loadLibrary("android_servers");
nativeInit();
// Check whether we failed to shut down last time we tried.
// This call may not return.
@@ -359,6 +358,10 @@ public final class SystemServer {
// Set up the Application instance for the system process and get started.
mActivityManagerService.setSystemProcess();
// The sensor service needs access to package manager service, app ops
// service, and permissions service, therefore we start it after them.
startSensorService();
}
/**

View File

@@ -57,6 +57,11 @@ public class ServiceManagerPermissionTests extends TestCase {
public String[] getPackagesForUid(int uid) {
return new String[0];
}
@Override
public boolean isRuntimePermission(String permission) {
return false;
}
};
ServiceManagerNative.asInterface(BinderInternal.getContextObject())
.setPermissionController(pc);