1 /*
2  * Copyright (C) 2021 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.systemui.clipboardoverlay;
18 
19 import static java.util.Objects.requireNonNull;
20 
21 import android.app.Activity;
22 import android.content.ClipData;
23 import android.content.ClipDescription;
24 import android.content.ClipboardManager;
25 import android.content.pm.PackageManager;
26 import android.graphics.Insets;
27 import android.os.Bundle;
28 import android.os.PersistableBundle;
29 import android.text.Editable;
30 import android.util.Log;
31 import android.view.View;
32 import android.view.ViewGroup;
33 import android.view.WindowInsets;
34 import android.view.inputmethod.InputMethodManager;
35 import android.widget.EditText;
36 import android.widget.TextView;
37 
38 import androidx.annotation.NonNull;
39 
40 import com.android.systemui.res.R;
41 
42 /**
43  * Lightweight activity for editing text clipboard contents
44  */
45 public class EditTextActivity extends Activity
46         implements ClipboardManager.OnPrimaryClipChangedListener {
47     private static final String TAG = "EditTextActivity";
48 
49     private EditText mEditText;
50     private ClipboardManager mClipboardManager;
51     private TextView mAttribution;
52     private boolean mSensitive;
53 
54     @Override
onCreate(Bundle savedInstanceState)55     protected void onCreate(Bundle savedInstanceState) {
56         super.onCreate(savedInstanceState);
57         setContentView(R.layout.clipboard_edit_text_activity);
58         findViewById(R.id.done_button).setOnClickListener((v) -> saveToClipboard());
59         mEditText = findViewById(R.id.edit_text);
60         mAttribution = findViewById(R.id.attribution);
61         mClipboardManager = requireNonNull(getSystemService(ClipboardManager.class));
62 
63         findViewById(R.id.editor_root).setOnApplyWindowInsetsListener(
64                 new View.OnApplyWindowInsetsListener() {
65                     @NonNull
66                     @Override
67                     public WindowInsets onApplyWindowInsets(@NonNull View view,
68                             @NonNull WindowInsets windowInsets) {
69                         Insets insets = windowInsets.getInsets(WindowInsets.Type.systemBars());
70                         ViewGroup.MarginLayoutParams layoutParams =
71                                 (ViewGroup.MarginLayoutParams) view.getLayoutParams();
72                         layoutParams.leftMargin = insets.left;
73                         layoutParams.bottomMargin = insets.bottom;
74                         layoutParams.rightMargin = insets.right;
75                         layoutParams.topMargin = insets.top;
76                         view.setLayoutParams(layoutParams);
77                         return WindowInsets.CONSUMED;
78                     }
79                 });
80     }
81 
82     @Override
onStart()83     protected void onStart() {
84         super.onStart();
85         ClipData clip = mClipboardManager.getPrimaryClip();
86         if (clip == null) {
87             finish();
88             return;
89         }
90         PackageManager pm = getApplicationContext().getPackageManager();
91         try {
92             CharSequence label = pm.getApplicationLabel(
93                     pm.getApplicationInfo(mClipboardManager.getPrimaryClipSource(),
94                             PackageManager.ApplicationInfoFlags.of(0)));
95             mAttribution.setText(getResources().getString(R.string.clipboard_edit_source, label));
96         } catch (PackageManager.NameNotFoundException e) {
97             Log.w(TAG, "Package not found: " + mClipboardManager.getPrimaryClipSource(), e);
98         }
99         mEditText.setText(clip.getItemAt(0).getText().toString());
100         mEditText.requestFocus();
101         mEditText.setSelection(0);
102         mSensitive = clip.getDescription().getExtras() != null
103                 && clip.getDescription().getExtras()
104                 .getBoolean(ClipDescription.EXTRA_IS_SENSITIVE);
105         mClipboardManager.addPrimaryClipChangedListener(this);
106     }
107 
108     @Override
onPause()109     protected void onPause() {
110         mClipboardManager.removePrimaryClipChangedListener(this);
111         super.onPause();
112     }
113 
114     @Override // ClipboardManager.OnPrimaryClipChangedListener
onPrimaryClipChanged()115     public void onPrimaryClipChanged() {
116         hideIme();
117         finish();
118     }
119 
saveToClipboard()120     private void saveToClipboard() {
121         hideIme();
122         Editable editedText = mEditText.getText();
123         editedText.clearSpans();
124         ClipData clip = ClipData.newPlainText("text", editedText);
125         PersistableBundle extras = new PersistableBundle();
126         extras.putBoolean(ClipDescription.EXTRA_IS_SENSITIVE, mSensitive);
127         clip.getDescription().setExtras(extras);
128         mClipboardManager.setPrimaryClip(clip);
129         finish();
130     }
131 
hideIme()132     private void hideIme() {
133         InputMethodManager imm = getSystemService(InputMethodManager.class);
134         imm.hideSoftInputFromWindow(mEditText.getWindowToken(), 0);
135     }
136 }
137