[高通SDM450][Android9.0]CTA认证--蓝牙、WIFI申请权限

文章目录

    • 开发平台基本信息
    • 问题描述
    • 解决方法

开发平台基本信息

芯片: 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(

你可能感兴趣的:(CTA认证-A9,Android9.0,framework,Android9.0,CTA,蓝牙WIFI授权,WLAN)