芯片: SDM450
版本: Android 9.0
kernel: msm-4.9
设备在进行入网认证的时候,实验室要求应用在使用特殊权限的时候,需要告知用户,要用户授权才能使用相应的权限;在高版本的安卓系统里,类似相机、位置这些权限都能自动申请,但是,像蓝牙、wifi的使用,是没有弹框提示用户授权的,实验室要求,蓝牙、wifi同样需要弹框提示用户授权。
diff --git a/frameworks/base/core/java/android/app/AppOpsManager.java b/frameworks/base/core/java/android/app/AppOpsManager.java
index c58b91e..990be3b 100644
--- a/frameworks/base/core/java/android/app/AppOpsManager.java
+++ b/frameworks/base/core/java/android/app/AppOpsManager.java
@@ -598,6 +598,7 @@ public class AppOpsManager {
/** @hide */
public static final String OPSTR_BLUETOOTH_SCAN = "android:bluetooth_scan";
+ public static final int OP_BLUETOOTH_ADMIN = 65;
// Warning: If an permission is added here it also has to be added to
// com.android.packageinstaller.permission.utils.EventLogger
private static final int[] RUNTIME_AND_APPOP_PERMISSIONS_OPS = {
diff --git a/frameworks/base/core/res/res/layout/permission_confirmation_dialog.xml b/frameworks/base/core/res/res/layout/permission_confirmation_dialog.xml
new file mode 100755
index 0000000..472602b
--- /dev/null
+++ b/frameworks/base/core/res/res/layout/permission_confirmation_dialog.xml
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (c) 2015, The Linux Foundation. All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials provided
+ with the distribution.
+ * Neither the name of The Linux Foundation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-->
+<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" />
+
+ <TableLayout android:id="@+id/permission_remember_layout"
+ android:shrinkColumns="1"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:paddingLeft="16dip"
+ android:paddingRight="16dip">
+
+ <TableRow
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" >
+ <RelativeLayout android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:paddingTop="12dip"
+ android:paddingLeft="8dip" >
+ <CheckBox android:id="@+id/permission_remember_choice_checkbox"
+ android:paddingTop="11dip"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+ </RelativeLayout>
+ <TextView android:id="@+id/permission_remember_choice_text"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:paddingTop="18dip"
+ android:text="@string/permission_remember_choice" />
+ </TableRow>
+
+ </TableLayout>
+
+</LinearLayout>
diff --git a/frameworks/base/core/res/res/values-zh-rCN/strings.xml b/frameworks/base/core/res/res/values-zh-rCN/strings.xml
index bc5e1a5..2b928eb 100644
--- a/frameworks/base/core/res/res/values-zh-rCN/strings.xml
+++ b/frameworks/base/core/res/res/values-zh-rCN/strings.xml
@@ -1886,4 +1886,7 @@
<string name="notification_appops_microphone_active" msgid="4335305527588191730">"麦克风"</string>
<string name="notification_appops_overlay_active" msgid="633813008357934729">"显示在屏幕上其他应用的上层"</string>
<string name="car_loading_profile" msgid="3545132581795684027">"正在加载"</string>
+ <!-- add by raul -->
+ <string name="permission_remember_choice">"永远记住"</string>
+
</resources>
diff --git a/frameworks/base/core/res/res/values/arrays.xml b/frameworks/base/core/res/res/values/arrays.xml
index 733878b..a7d661b 100644
--- a/frameworks/base/core/res/res/values/arrays.xml
+++ b/frameworks/base/core/res/res/values/arrays.xml
@@ -184,5 +184,10 @@
<item>@string/unpin_target</item>
<item>@string/app_info</item>
</string-array>
+
+ <string-array name="app_ops_labels">
+ <item>Trying to enable WLAN</item>
+ <item>Trying to enable BT</item>
+ </string-array>
</resources>
diff --git a/frameworks/base/core/res/res/values/strings.xml b/frameworks/base/core/res/res/values/strings.xml
index f660046..5cd775b 100644
--- a/frameworks/base/core/res/res/values/strings.xml
+++ b/frameworks/base/core/res/res/values/strings.xml
@@ -4995,4 +4995,13 @@
<!-- Strings for car -->
<!-- String displayed when loading a user in the car [CHAR LIMIT=30] -->
<string name="car_loading_profile">Loading</string>
+
+ <!-- add by raul -->
+ <string name="permission_remember_choice">Remember</string>
+
+ <string name="other_permissions">other permissions</string>
+ <string name="permission_title">Permission</string>
+ <string name="allow_button">Allow</string>
+ <string name="deny_button">Deny</string>
+
</resources>
diff --git a/frameworks/base/core/res/res/values/symbols.xml b/frameworks/base/core/res/res/values/symbols.xml
index 9c78d86..7031f64 100644
--- a/frameworks/base/core/res/res/values/symbols.xml
+++ b/frameworks/base/core/res/res/values/symbols.xml
@@ -37,6 +37,10 @@
<java-symbol type="id" name="activity_chooser_view_content" />
<java-symbol type="id" name="alertTitle" />
<java-symbol type="id" name="allow_button" />
+ <java-symbol type="id" name="permission_text" />
+ <java-symbol type="id" name="permission_remember_layout" />
+ <java-symbol type="id" name="permission_remember_choice_checkbox" />
+ <java-symbol type="id" name="permission_remember_choice_text" />
<java-symbol type="id" name="alwaysUse" />
<java-symbol type="id" name="amPm" />
<java-symbol type="id" name="authtoken_type" />
@@ -568,6 +572,9 @@
<java-symbol type="string" name="sms" />
<java-symbol type="string" name="sms_desc" />
<java-symbol type="string" name="add_contact" />
+ <java-symbol type="string" name="permission_title" />
+ <java-symbol type="string" name="allow_button" />
+ <java-symbol type="string" name="deny_button" />
<java-symbol type="string" name="add_contact_desc" />
<java-symbol type="string" name="view_calendar" />
<java-symbol type="string" name="view_calendar_desc" />
@@ -1649,6 +1656,7 @@
<java-symbol type="attr" name="dialogCustomTitleDecorLayout" />
<java-symbol type="attr" name="dialogTitleDecorLayout" />
<java-symbol type="attr" name="dialogTitleIconsDecorLayout" />
+ <java-symbol type="array" name="app_ops_labels" />
<java-symbol type="bool" name="config_allowAllRotations" />
<java-symbol type="bool" name="config_annoy_dianne" />
<java-symbol type="bool" name="config_carDockEnablesAccelerometer" />
@@ -2150,6 +2158,7 @@
<java-symbol type="integer" name="config_maxResolverActivityColumns" />
<java-symbol type="array" name="config_notificationSignalExtractors" />
+ <java-symbol type="layout" name="permission_confirmation_dialog" />
<java-symbol type="layout" name="notification_material_action" />
<java-symbol type="layout" name="notification_material_action_list" />
<java-symbol type="layout" name="notification_material_action_tombstone" />
diff --git a/frameworks/base/services/core/java/com/android/server/AppOpsService.java b/frameworks/base/services/core/java/com/android/server/AppOpsService.java
old mode 100644
new mode 100755
index 786d757..8186b75
--- a/frameworks/base/services/core/java/com/android/server/AppOpsService.java
+++ b/frameworks/base/services/core/java/com/android/server/AppOpsService.java
@@ -98,11 +98,15 @@ import java.util.Map;
import static android.app.AppOpsManager._NUM_UID_STATE;
import static android.app.AppOpsManager.UID_STATE_BACKGROUND;
import static android.app.AppOpsManager.UID_STATE_CACHED;
+import android.os.Looper;
import static android.app.AppOpsManager.UID_STATE_FOREGROUND;
import static android.app.AppOpsManager.UID_STATE_FOREGROUND_SERVICE;
import static android.app.AppOpsManager.UID_STATE_LAST_NON_RESTRICTED;
import static android.app.AppOpsManager.UID_STATE_PERSISTENT;
import static android.app.AppOpsManager.UID_STATE_TOP;
+import android.util.Log;
+import android.util.Slog;
+import com.android.server.PermissionDialogReqQueue.PermissionDialogReq;
public class AppOpsService extends IAppOpsService.Stub {
static final String TAG = "AppOps";
@@ -173,7 +177,7 @@ public class AppOpsService extends IAppOpsService.Stub {
Context mContext;
final AtomicFile mFile;
final Handler mHandler;
-
+ final Looper mLooper;
private final AppOpsManagerInternalImpl mAppOpsManagerInternal
= new AppOpsManagerInternalImpl();
@@ -407,6 +411,7 @@ public class AppOpsService extends IAppOpsService.Stub {
long time[] = new long[_NUM_UID_STATE];
long rejectTime[] = new long[_NUM_UID_STATE];
int startNesting;
+ public PermissionDialogReqQueue dialogReqQueue;
long startRealtime;
Op(UidState _uidState, String _packageName, int _op) {
@@ -415,6 +420,7 @@ public class AppOpsService extends IAppOpsService.Stub {
packageName = _packageName;
op = _op;
mode = AppOpsManager.opToDefaultMode(op);
+ dialogReqQueue = new PermissionDialogReqQueue();
}
boolean hasAnyTime() {
@@ -578,6 +584,7 @@ public class AppOpsService extends IAppOpsService.Stub {
mFile = new AtomicFile(storagePath, "appops");
mHandler = handler;
mConstants = new Constants(mHandler);
+ mLooper = Looper.myLooper();
readState();
}
@@ -1559,16 +1566,18 @@ public class AppOpsService extends IAppOpsService.Stub {
if (resolvedPackageName == null) {
return AppOpsManager.MODE_IGNORED;
}
+
return noteOperationUnchecked(code, uid, resolvedPackageName, 0, null);
}
private int noteOperationUnchecked(int code, int uid, String packageName,
int proxyUid, String proxyPackageName) {
+ PermissionDialogReq req = new PermissionDialogReq();
synchronized (this) {
final Ops ops = getOpsRawLocked(uid, packageName, true /* edit */,
false /* uidMismatchExpected */);
if (ops == null) {
- if (DEBUG) Slog.d(TAG, "noteOperation: no op for code " + code + " uid " + uid
+ Slog.d("raul", "noteOperation: no op for code " + code + " uid " + uid
+ " package " + packageName);
return AppOpsManager.MODE_ERRORED;
}
@@ -1578,12 +1587,25 @@ public class AppOpsService extends IAppOpsService.Stub {
}
final UidState uidState = ops.uidState;
if (op.duration == -1) {
- Slog.w(TAG, "Noting op not finished: uid " + uid + " pkg " + packageName
+ Slog.w("raul", "Noting op not finished: uid " + uid + " pkg " + packageName
+ " code " + code + " time=" + op.time[uidState.state]
+ " duration=" + op.duration);
}
op.duration = 0;
final int switchCode = AppOpsManager.opToSwitch(code);
+
+ if (code == AppOpsManager.OP_CHANGE_WIFI_STATE
+ || code == AppOpsManager.OP_BLUETOOTH_ADMIN) {
+
+ final Op switchOp = switchCode
+ != code ? getOpLocked(ops, switchCode, true) : op;
+ if (Looper.myLooper() == mLooper) {
+ return switchOp.mode;
+ }
+
+ req = askOperationLocked(code, uid, packageName, switchOp);
+ } else {
+
// If there is a non-default per UID policy (we set UID op mode only if
// non-default) it takes over, otherwise use the per package policy.
if (uidState.opModes != null && uidState.opModes.indexOfKey(switchCode) >= 0) {
@@ -1614,8 +1636,10 @@ public class AppOpsService extends IAppOpsService.Stub {
op.proxyPackageName = proxyPackageName;
return AppOpsManager.MODE_ALLOWED;
}
+ }
+ return req.get(); //this method could not added to the synchronized
}
-
+
@Override
public void startWatchingActive(int[] ops, IAppOpsActiveCallback callback) {
int watchedUid = -1;
@@ -3582,6 +3606,47 @@ public class AppOpsService extends IAppOpsService.Stub {
}
return packageName;
}
+
+
+ final class AskRunnable implements Runnable {
+ final int code;
+ final int uid;
+ final String packageName;
+ final Op op;
+ final PermissionDialogReq request;
+
+ public AskRunnable(int code, int uid, String packageName, Op op,
+ PermissionDialogReq request) {
+ super();
+ this.code = code;
+ this.uid = uid;
+ this.packageName = packageName;
+ this.op = op;
+ this.request = request;
+ }
+
+ @Override
+ public void run() {
+ PermissionDialog permDialog = null;
+ synchronized (AppOpsService.this) {
+ op.dialogReqQueue.register(request);
+ if (op.dialogReqQueue.getDialog() == null) {
+ permDialog = new PermissionDialog(mContext,
+ AppOpsService.this, code, uid, packageName);
+ op.dialogReqQueue.setDialog(permDialog);
+ }
+ }
+ if (permDialog != null) {
+ permDialog.show();
+ }
+ }
+ }
+
+ private PermissionDialogReq askOperationLocked(int code, int uid, String packageName, Op op) {
+ PermissionDialogReq request = new PermissionDialogReq();
+ mHandler.post(new AskRunnable(code, uid, packageName, op, request));
+ return request;
+ }
private static int resolveUid(String packageName) {
if (packageName == null) {
@@ -3601,7 +3666,60 @@ public class AppOpsService extends IAppOpsService.Stub {
}
return -1;
}
+
+ public void notifyOperation(int code, int uid, String packageName,
+ int mode, boolean remember) {
+ verifyIncomingUid(uid);
+ verifyIncomingOp(code);
+ ArrayList<ModeCallback> repCbs = null;
+ int switchCode = AppOpsManager.opToSwitch(code);
+ synchronized (this) {
+ //recordOperationLocked(code, uid, packageName, mode);
+ Op op = getOpLocked(switchCode, uid, packageName, true);
+ if (op != null) {
+ // Send result to all waiting client
+ if (op.dialogReqQueue.getDialog() != null) {
+ op.dialogReqQueue.notifyAll(mode);
+ op.dialogReqQueue.setDialog(null);
+ }
+ if (remember) {
+ // op.remember = true;
+ // writeUidStateMode(code, uid, mode);
+ ArraySet<ModeCallback> cbs = mOpModeWatchers.get(switchCode);
+ if (cbs != null) {
+ if (repCbs == null) {
+ repCbs = new ArrayList<ModeCallback>();
+ }
+ repCbs.addAll(cbs);
+ }
+ cbs = mPackageModeWatchers.get(packageName);
+ if (cbs != null) {
+ if (repCbs == null) {
+ repCbs = new ArrayList<ModeCallback>();
+ }
+ repCbs.addAll(cbs);
+ }
+ //if (mode == getDefaultMode(op.op, op.uid, op.packageName)) {
+ // 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(switchCode, uid, packageName);
+ } catch (RemoteException e) {
+ Log.w(TAG, "repCbs.get(i).mCallback.opChanged() error ", e);
+ }
+ }
+ }
+ }
+
private static String[] getPackagesForUid(int uid) {
String[] packageNames = null;
try {
diff --git a/frameworks/base/services/core/java/com/android/server/BasePermissionDialog.java b/frameworks/base/services/core/java/com/android/server/BasePermissionDialog.java
new file mode 100755
index 0000000..bf442d6
--- /dev/null
+++ b/frameworks/base/services/core/java/com/android/server/BasePermissionDialog.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2015-2016, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.android.server;
+
+import android.app.AlertDialog;
+import android.content.Context;
+import android.os.Handler;
+import android.os.Message;
+import android.view.KeyEvent;
+import android.view.WindowManager;
+import android.widget.Button;
+import com.android.internal.R;
+
+public class BasePermissionDialog extends AlertDialog {
+ public BasePermissionDialog(Context dialogCon) {
+ super(dialogCon, com.android.internal.R.style.Theme_Dialog_AppError);
+ getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
+ getWindow().setFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
+ WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
+ WindowManager.LayoutParams permInfo = getWindow().getAttributes();
+ permInfo.setTitle("Permission Dialog");
+ getWindow().setAttributes(permInfo);
+ setIconAttribute(R.attr.alertDialogIcon);
+ }
+
+ public boolean dispatchKeyEvent(KeyEvent event) {
+ if (mState) {
+ return true;
+ }
+ return super.dispatchKeyEvent(event);
+ }
+
+ public void onStart() {
+ super.onStart();
+ setEnabled(false);
+ mInfoHandler.sendMessage(mInfoHandler.obtainMessage(0));
+ }
+
+ private Handler mInfoHandler = new Handler() {
+ public void handleMessage(Message msg) {
+ if (msg.what == 0) {
+ mState = false;
+ setEnabled(true);
+ }
+ }
+ };
+
+ private void setEnabled(boolean setState) {
+ Button btn = (Button) findViewById(R.id.button1);
+ if (btn != null) {
+ btn.setEnabled(setState);
+ }
+ btn = (Button) findViewById(R.id.button2);
+ if (btn != null) {
+ btn.setEnabled(setState);
+ }
+ btn = (Button) findViewById(R.id.button3);
+ if (btn != null) {
+ btn.setEnabled(setState);
+ }
+ }
+
+ private boolean mState = true;
+}
diff --git a/frameworks/base/services/core/java/com/android/server/BluetoothManagerService.java b/frameworks/base/services/core/java/com/android/server/BluetoothManagerService.java
index 005f0ac..c998e8b 100644
--- a/frameworks/base/services/core/java/com/android/server/BluetoothManagerService.java
+++ b/frameworks/base/services/core/java/com/android/server/BluetoothManagerService.java
@@ -33,6 +33,7 @@ import android.bluetooth.IBluetoothStateChangeCallback;
import android.content.ActivityNotFoundException;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
+import android.app.AppOpsManager;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
@@ -943,7 +944,25 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
Slog.d(TAG, "enable(" + packageName + "): mBluetooth =" + mBluetooth + " mBinding = "
+ mBinding + " mState = " + BluetoothAdapter.nameForState(mState));
}
+
+ AppOpsManager mAppOpsManager = mContext.getSystemService(AppOpsManager.class);
+ // String packageName = mContext.getPackageManager().getNameForUid(Binder.getCallingUid());
+ Slog.d("raul","able===1===");
+ Slog.d("raul","ssss Binder.getCallingUid()="+Binder.getCallingUid());
+ if ( (packageName.indexOf("android.uid.systemui") != 0)
+ && (packageName.indexOf("android.uid.system") != 0)) {
+
+ Slog.d("raul","able===2===");
+
+ int result = mAppOpsManager.noteOp(AppOpsManager.OP_BLUETOOTH_ADMIN,
+ Binder.getCallingUid(), packageName);
+ if (result == AppOpsManager.MODE_IGNORED) {
+ return false;
+ }
+ }
+
+
synchronized (mReceiver) {
mQuietEnableExternal = false;
if (!mEnableBLE) {
@@ -983,7 +1002,22 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
if (DBG) {
Slog.d(TAG, "disable(): mBluetooth = " + mBluetooth + " mBinding = " + mBinding);
}
-
+
+ AppOpsManager mAppOpsManager = mContext.getSystemService(AppOpsManager.class);
+ // String packageName = mContext.getPackageManager().getNameForUid(Binder.getCallingUid());
+ Slog.d("raul","disable===1===");
+ if ( (packageName.indexOf("android.uid.systemui") != 0)
+ && (packageName.indexOf("android.uid.system") != 0)) {
+
+ Slog.d("raul","disable===2===");
+
+ int result = mAppOpsManager.noteOp(AppOpsManager.OP_BLUETOOTH_ADMIN,
+ Binder.getCallingUid(), packageName);
+ if (result == AppOpsManager.MODE_IGNORED) {
+ return false;
+ }
+ }
+
synchronized (mReceiver) {
if (persist) {
persistBluetoothSetting(BLUETOOTH_OFF);
diff --git a/frameworks/base/services/core/java/com/android/server/PermissionDialog.java b/frameworks/base/services/core/java/com/android/server/PermissionDialog.java
new file mode 100755
index 0000000..c8b8135
--- /dev/null
+++ b/frameworks/base/services/core/java/com/android/server/PermissionDialog.java
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2015-2016, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.android.server;
+
+import android.os.Message;
+import android.os.Handler;
+import android.widget.TextView;
+import android.widget.CheckBox;
+import android.view.WindowManager;
+import android.view.View;
+import android.content.res.Resources;
+import android.content.pm.PackageManager;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.app.AppOpsManager;
+import com.android.internal.R;
+
+public class PermissionDialog extends BasePermissionDialog {
+ private final int mDef;
+ private final String inputPackage;
+ private final AppOpsService opsServ;
+ private final static String TAG = "PermInfo";
+ private View viewId;
+ private int inputId;
+ private CheckBox checkSta;
+ private Context contId;
+ final CharSequence[] mOpLabels;
+ static final int IGNORED_REQ = 0x4;
+ static final int IGNORED_REQ_TIMEOUT = 0x8;
+ static final long TIMEOUT_WAIT = 15 * 1000;
+ static final int ALLOWED_REQ = 0x2;
+
+ public PermissionDialog(Context contextId, AppOpsService opsService,
+ int defInf, int idInfo, String packageName) {
+ super(contextId);
+ opsServ = opsService;
+ inputPackage = packageName;
+ contId = contextId;
+ mDef = defInf;
+ Resources rId = contextId.getResources();
+ inputId = idInfo;
+ mOpLabels = rId.getTextArray(
+ R.array.app_ops_labels);
+ setCancelable(false);
+ setButton(DialogInterface.BUTTON_POSITIVE,
+ rId.getString(R.string.allow_button),
+ myHandle.obtainMessage(ALLOWED_REQ));
+ setButton(DialogInterface.BUTTON_NEGATIVE,
+ rId.getString(R.string.deny_button),
+ myHandle.obtainMessage(IGNORED_REQ));
+ setTitle(rId.getString(R.string.permission_title));
+ WindowManager.LayoutParams paraDef = getWindow().getAttributes();
+ paraDef.setTitle("Permission: " + getAppName(inputPackage));
+ paraDef.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SYSTEM_ERROR
+ | WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
+ getWindow().setAttributes(paraDef);
+ viewId = getLayoutInflater().inflate(
+ R.layout.permission_confirmation_dialog, null);
+ TextView textId = (TextView) viewId.findViewById(
+ R.id.permission_text);
+ checkSta = (CheckBox) viewId.findViewById(
+ R.id.permission_remember_choice_checkbox);
+ TextView textRem = (TextView) viewId.findViewById(
+ R.id.permission_remember_choice_text);
+ checkSta.setVisibility(View.INVISIBLE);
+ textRem.setVisibility(View.INVISIBLE);
+
+
+
+ String appName = getAppName(inputPackage);
+ if (appName == null)
+ appName = inputPackage;
+
+ android.util.Log.i("raul","mDef="+mDef);
+
+ if(mDef== 71){
+ textId.setText(appName + ": " + mOpLabels[0]);
+ }else{
+ textId.setText(appName + ": " + mOpLabels[mDef-64]);
+ }
+ setView(viewId);
+ myHandle.sendMessageDelayed(myHandle.obtainMessage(IGNORED_REQ_TIMEOUT), TIMEOUT_WAIT);
+ }
+
+ private final Handler myHandle = new Handler() {
+ public void handleMessage(Message mess) {
+ int runSet;
+ boolean keepIt = checkSta.isChecked();
+ switch (mess.what) {
+ case ALLOWED_REQ:
+ runSet = AppOpsManager.MODE_ALLOWED;
+ break;
+ case IGNORED_REQ:
+ runSet = AppOpsManager.MODE_IGNORED;
+ break;
+ default:
+ runSet = AppOpsManager.MODE_IGNORED;
+ keepIt = false;
+ }
+ opsServ.notifyOperation(mDef, inputId, inputPackage, runSet, keepIt);
+ dismiss();
+ }
+ };
+
+ private String getAppName(String inputName) {
+ PackageManager packMan = contId.getPackageManager();
+ ApplicationInfo runInfo = null;
+ try {
+ runInfo = packMan.getApplicationInfo(inputName, PackageManager.GET_DISABLED_COMPONENTS
+ | PackageManager.GET_UNINSTALLED_PACKAGES);
+ } catch (final NameNotFoundException e) {
+ return null;
+ }
+ if (runInfo != null) {
+ return (String) packMan.getApplicationLabel(runInfo);
+ }
+ return null;
+ }
+}
diff --git a/frameworks/base/services/core/java/com/android/server/PermissionDialogReqQueue.java b/frameworks/base/services/core/java/com/android/server/PermissionDialogReqQueue.java
new file mode 100755
index 0000000..64a7885
--- /dev/null
+++ b/frameworks/base/services/core/java/com/android/server/PermissionDialogReqQueue.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2015-2016, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.android.server;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class PermissionDialogReqQueue {
+ public PermissionDialog getDialog() {
+ return mDialog;
+ }
+
+ public void setDialog(PermissionDialog mDialog) {
+ this.mDialog = mDialog;
+ }
+
+ public final static class PermissionDialogReq {
+ public void set(int res) {
+ synchronized (this) {
+ mHasResult = true;
+ mResult = res;
+ notifyAll();
+ }
+ }
+
+ public int get() {
+ synchronized (this) {
+ while (!mHasResult) {
+ try {
+ wait();
+ } catch (InterruptedException e) {
+ }
+ }
+ }
+ return mResult;
+ }
+
+ boolean mHasResult = false;
+ int mResult;
+ }
+
+ private PermissionDialog mDialog;
+ private List<PermissionDialogReq> mResultList;
+
+ public PermissionDialogReqQueue() {
+ mDialog = null;
+ mResultList = new ArrayList<PermissionDialogReq>();
+ }
+
+ public void register(PermissionDialogReq res) {
+ synchronized (this) {
+ mResultList.add(res);
+ }
+ }
+
+ public void notifyAll(int mode) {
+ synchronized (this) {
+ while (mResultList.size() != 0) {
+ PermissionDialogReq res = mResultList.get(0);
+ res.set(mode);
+ mResultList.remove(0);
+ }
+ }
+ }
+}
diff --git a/frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiServiceImpl.java b/frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiServiceImpl.java
index 01e7344..6988da8 100644
--- a/frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiServiceImpl.java
+++ b/frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiServiceImpl.java
@@ -38,6 +38,10 @@ import static com.android.server.wifi.WifiController.CMD_SET_AP;
import static com.android.server.wifi.WifiController.CMD_USER_PRESENT;
import static com.android.server.wifi.WifiController.CMD_WIFI_TOGGLED;
+import android.os.Binder;
+import android.os.Build;
+import android.app.AppOpsManager;
+
import android.Manifest;
import android.annotation.CheckResult;
import android.app.ActivityManager;
@@ -881,7 +885,16 @@ public class WifiServiceImpl extends IWifiManager.Stub {
Slog.d(TAG, "setWifiEnabled: " + enable + " pid=" + Binder.getCallingPid()
+ ", uid=" + Binder.getCallingUid() + ", package=" + packageName);
- mLog.info("setWifiEnabled package=% uid=% enable=%").c(packageName)
+
+ if( (packageName.indexOf("android.uid.systemui") !=0) && (packageName.indexOf("android.uid.system") != 0)) {
+ AppOpsManager mAppOpsManager = mContext.getSystemService(AppOpsManager.class);
+ int result = mAppOpsManager.noteOp(AppOpsManager.OP_CHANGE_WIFI_STATE,Binder.getCallingUid(),packageName);
+ if(result == AppOpsManager.MODE_IGNORED){
+ return false;
+ }
+ }
+
+ mLog.info("setWifiEnabled package=% uid=% enable=%").c(packageName)
.c(Binder.getCallingUid()).c(enable).flush();
boolean isFromSettings = checkNetworkSettingsPermission(