1 /*
2  * Copyright (C) 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
5  * except in compliance with the License. You may obtain a copy of the License at
6  *
7  *      http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software distributed under the
10  * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
11  * KIND, either express or implied. See the License for the specific language governing
12  * permissions and limitations under the License.
13  */
14 
15 package com.android.systemui;
16 
17 import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
18 
19 import android.annotation.Nullable;
20 import android.app.Activity;
21 import android.app.AlertDialog;
22 import android.app.slice.SliceManager;
23 import android.app.slice.SliceProvider;
24 import android.content.DialogInterface;
25 import android.content.DialogInterface.OnClickListener;
26 import android.content.DialogInterface.OnDismissListener;
27 import android.content.pm.PackageItemInfo;
28 import android.content.pm.PackageManager;
29 import android.content.pm.PackageManager.NameNotFoundException;
30 import android.net.Uri;
31 import android.os.Bundle;
32 import android.text.BidiFormatter;
33 import android.util.EventLog;
34 import android.util.Log;
35 import android.widget.CheckBox;
36 import android.widget.TextView;
37 
38 public class SlicePermissionActivity extends Activity implements OnClickListener,
39         OnDismissListener {
40 
41     private static final String TAG = "SlicePermissionActivity";
42 
43     private CheckBox mAllCheckbox;
44 
45     private Uri mUri;
46     private String mCallingPkg;
47     private String mProviderPkg;
48 
49     @Override
onCreate(Bundle savedInstanceState)50     protected void onCreate(Bundle savedInstanceState) {
51         super.onCreate(savedInstanceState);
52 
53         // Verify intent is valid
54         mUri = getIntent().getParcelableExtra(SliceProvider.EXTRA_BIND_URI);
55         mCallingPkg = getIntent().getStringExtra(SliceProvider.EXTRA_PKG);
56         if (mUri == null
57                 || !SliceProvider.SLICE_TYPE.equals(getContentResolver().getType(mUri))
58                 || !SliceManager.ACTION_REQUEST_SLICE_PERMISSION.equals(getIntent().getAction())) {
59             Log.e(TAG, "Intent is not valid");
60             finish();
61             return;
62         }
63 
64         try {
65             PackageManager pm = getPackageManager();
66             mProviderPkg = pm.resolveContentProvider(mUri.getAuthority(),
67                     PackageManager.GET_META_DATA).applicationInfo.packageName;
68             verifyCallingPkg();
69             CharSequence app1 = BidiFormatter.getInstance().unicodeWrap(pm.getApplicationInfo(
70                     mCallingPkg, 0).loadSafeLabel(pm, PackageItemInfo.DEFAULT_MAX_LABEL_SIZE_PX,
71                     PackageItemInfo.SAFE_LABEL_FLAG_TRIM
72                             | PackageItemInfo.SAFE_LABEL_FLAG_FIRST_LINE).toString());
73             CharSequence app2 = BidiFormatter.getInstance().unicodeWrap(pm.getApplicationInfo(
74                     mProviderPkg, 0).loadSafeLabel(pm, PackageItemInfo.DEFAULT_MAX_LABEL_SIZE_PX,
75                     PackageItemInfo.SAFE_LABEL_FLAG_TRIM
76                             | PackageItemInfo.SAFE_LABEL_FLAG_FIRST_LINE).toString());
77             AlertDialog dialog = new AlertDialog.Builder(this)
78                     .setTitle(getString(R.string.slice_permission_title, app1, app2))
79                     .setView(R.layout.slice_permission_request)
80                     .setNegativeButton(R.string.slice_permission_deny, this)
81                     .setPositiveButton(R.string.slice_permission_allow, this)
82                     .setOnDismissListener(this)
83                     .create();
84             dialog.getWindow().addSystemFlags(SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
85             dialog.show();
86             TextView t1 = dialog.getWindow().getDecorView().findViewById(R.id.text1);
87             t1.setText(getString(R.string.slice_permission_text_1, app2));
88             TextView t2 = dialog.getWindow().getDecorView().findViewById(R.id.text2);
89             t2.setText(getString(R.string.slice_permission_text_2, app2));
90             mAllCheckbox = dialog.getWindow().getDecorView().findViewById(
91                     R.id.slice_permission_checkbox);
92             mAllCheckbox.setText(getString(R.string.slice_permission_checkbox, app1));
93         } catch (NameNotFoundException e) {
94             Log.e(TAG, "Couldn't find package", e);
95             finish();
96         }
97     }
98 
99     @Override
onClick(DialogInterface dialog, int which)100     public void onClick(DialogInterface dialog, int which) {
101         if (which == DialogInterface.BUTTON_POSITIVE) {
102             getSystemService(SliceManager.class).grantPermissionFromUser(mUri, mCallingPkg,
103                     mAllCheckbox.isChecked());
104         }
105         finish();
106     }
107 
108     @Override
onDismiss(DialogInterface dialog)109     public void onDismiss(DialogInterface dialog) {
110         finish();
111     }
112 
verifyCallingPkg()113     private void verifyCallingPkg() {
114         final String providerPkg = getIntent().getStringExtra("provider_pkg");
115         if (providerPkg == null || mProviderPkg.equals(providerPkg)) return;
116         final String callingPkg = getCallingPkg();
117         EventLog.writeEvent(0x534e4554, "159145361", getUid(callingPkg));
118     }
119 
120     @Nullable
getCallingPkg()121     private String getCallingPkg() {
122         final Uri referrer = getReferrer();
123         if (referrer == null) return null;
124         return referrer.getHost();
125     }
126 
getUid(@ullable final String pkg)127     private int getUid(@Nullable final String pkg) {
128         if (pkg == null) return -1;
129         try {
130             return getPackageManager().getApplicationInfo(pkg, 0).uid;
131         } catch (NameNotFoundException e) {
132         }
133         return -1;
134     }
135 }
136