remove android 4 compatibility code

This commit is contained in:
adbenitez 2024-11-21 01:16:20 +01:00
parent a51013cc00
commit 0ca92ec6b5
74 changed files with 207 additions and 1077 deletions

View file

@ -28,11 +28,6 @@ public class FcmReceiveService extends FirebaseMessagingService {
private static volatile String prefixedToken; private static volatile String prefixedToken;
public static void register(Context context) { public static void register(Context context) {
if (Build.VERSION.SDK_INT < 19) {
Log.w(TAG, "FCM not available on SDK < 19");
triedRegistering = true;
return;
}
if (FcmReceiveService.prefixedToken != null) { if (FcmReceiveService.prefixedToken != null) {
Log.i(TAG, "FCM already registered"); Log.i(TAG, "FCM already registered");

View file

@ -36,7 +36,6 @@ import org.thoughtcrime.securesms.connect.KeepAliveService;
import org.thoughtcrime.securesms.connect.NetworkStateReceiver; import org.thoughtcrime.securesms.connect.NetworkStateReceiver;
import org.thoughtcrime.securesms.crypto.DatabaseSecret; import org.thoughtcrime.securesms.crypto.DatabaseSecret;
import org.thoughtcrime.securesms.crypto.DatabaseSecretProvider; import org.thoughtcrime.securesms.crypto.DatabaseSecretProvider;
import org.thoughtcrime.securesms.crypto.PRNGFixes;
import org.thoughtcrime.securesms.geolocation.DcLocationManager; import org.thoughtcrime.securesms.geolocation.DcLocationManager;
import org.thoughtcrime.securesms.jobmanager.JobManager; import org.thoughtcrime.securesms.jobmanager.JobManager;
import org.thoughtcrime.securesms.notifications.FcmReceiveService; import org.thoughtcrime.securesms.notifications.FcmReceiveService;
@ -178,7 +177,6 @@ public class ApplicationContext extends MultiDexApplication {
KeepAliveService.maybeStartSelf(this); KeepAliveService.maybeStartSelf(this);
initializeRandomNumberFix();
initializeLogging(); initializeLogging();
initializeJobManager(); initializeJobManager();
InChatSounds.getInstance(this); InChatSounds.getInstance(this);
@ -226,10 +224,6 @@ public class ApplicationContext extends MultiDexApplication {
return jobManager; return jobManager;
} }
private void initializeRandomNumberFix() {
PRNGFixes.apply();
}
private void initializeLogging() { private void initializeLogging() {
SignalProtocolLoggerProvider.setProvider(new AndroidSignalProtocolLogger()); SignalProtocolLoggerProvider.setProvider(new AndroidSignalProtocolLogger());
} }

View file

@ -152,10 +152,6 @@ public class ApplicationPreferencesActivity extends PassphraseRequiredActionBarA
this.findPreference(PREFERENCE_CATEGORY_HELP) this.findPreference(PREFERENCE_CATEGORY_HELP)
.setOnPreferenceClickListener(new CategoryClickListener(PREFERENCE_CATEGORY_HELP)); .setOnPreferenceClickListener(new CategoryClickListener(PREFERENCE_CATEGORY_HELP));
if (VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
tintIcons(getActivity());
}
DcHelper.getEventCenter(getActivity()).addObserver(DcContext.DC_EVENT_CONNECTIVITY_CHANGED, this); DcHelper.getEventCenter(getActivity()).addObserver(DcContext.DC_EVENT_CONNECTIVITY_CHANGED, this);
} }

View file

@ -33,9 +33,6 @@ public abstract class BaseActionBarActivity extends AppCompatActivity {
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
onPreCreate(); onPreCreate();
if (BaseActivity.isMenuWorkaroundRequired()) {
forceOverflowMenu();
}
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
} }
@ -46,20 +43,6 @@ public abstract class BaseActionBarActivity extends AppCompatActivity {
dynamicTheme.onResume(this); dynamicTheme.onResume(this);
} }
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
return (keyCode == KeyEvent.KEYCODE_MENU && BaseActivity.isMenuWorkaroundRequired()) || super.onKeyDown(keyCode, event);
}
@Override
public boolean onKeyUp(int keyCode, @NonNull KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_MENU && BaseActivity.isMenuWorkaroundRequired()) {
openOptionsMenu();
return true;
}
return super.onKeyUp(keyCode, event);
}
private void initializeScreenshotSecurity() { private void initializeScreenshotSecurity() {
if (Prefs.isScreenSecurityEnabled(this)) { if (Prefs.isScreenSecurityEnabled(this)) {
getWindow().addFlags(WindowManager.LayoutParams.FLAG_SECURE); getWindow().addFlags(WindowManager.LayoutParams.FLAG_SECURE);

View file

@ -1,28 +0,0 @@
package org.thoughtcrime.securesms;
import android.os.Build;
import android.os.Build.VERSION;
import android.os.Build.VERSION_CODES;
import androidx.annotation.NonNull;
import androidx.fragment.app.FragmentActivity;
import android.view.KeyEvent;
public abstract class BaseActivity extends FragmentActivity {
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
return (keyCode == KeyEvent.KEYCODE_MENU && isMenuWorkaroundRequired()) || super.onKeyDown(keyCode, event);
}
@Override
public boolean onKeyUp(int keyCode, @NonNull KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_MENU && isMenuWorkaroundRequired()) {
openOptionsMenu();
return true;
}
return super.onKeyUp(keyCode, event);
}
public static boolean isMenuWorkaroundRequired() {
return VERSION.SDK_INT < VERSION_CODES.KITKAT && ("LGE".equalsIgnoreCase(Build.MANUFACTURER) || "E6710".equalsIgnoreCase(Build.DEVICE));
}
}

View file

@ -364,9 +364,7 @@ public abstract class BaseConversationListFragment extends Fragment implements A
mode.setTitle("1"); mode.setTitle("1");
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { requireActivity().getWindow().setStatusBarColor(getResources().getColor(R.color.action_mode_status_bar));
requireActivity().getWindow().setStatusBarColor(getResources().getColor(R.color.action_mode_status_bar));
}
return true; return true;
} }
@ -395,11 +393,9 @@ public abstract class BaseConversationListFragment extends Fragment implements A
actionMode = null; actionMode = null;
getListAdapter().initializeBatchMode(false); getListAdapter().initializeBatchMode(false);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { TypedArray color = requireActivity().getTheme().obtainStyledAttributes(new int[]{android.R.attr.statusBarColor});
TypedArray color = requireActivity().getTheme().obtainStyledAttributes(new int[] {android.R.attr.statusBarColor}); requireActivity().getWindow().setStatusBarColor(color.getColor(0, Color.BLACK));
requireActivity().getWindow().setStatusBarColor(color.getColor(0, Color.BLACK)); color.recycle();
color.recycle();
}
Context context = getContext(); Context context = getContext();
if (context != null) { if (context != null) {

View file

@ -136,9 +136,7 @@ public class ContactSelectionListFragment extends Fragment
public boolean onCreateActionMode(ActionMode actionMode, Menu menu) { public boolean onCreateActionMode(ActionMode actionMode, Menu menu) {
MenuInflater inflater = getActivity().getMenuInflater(); MenuInflater inflater = getActivity().getMenuInflater();
inflater.inflate(R.menu.contact_list, menu); inflater.inflate(R.menu.contact_list, menu);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { getActivity().getWindow().setStatusBarColor(getResources().getColor(R.color.action_mode_status_bar));
getActivity().getWindow().setStatusBarColor(getResources().getColor(R.color.action_mode_status_bar));
}
setCorrectMenuVisibility(menu); setCorrectMenuVisibility(menu);
actionMode.setTitle("1"); actionMode.setTitle("1");
return true; return true;
@ -170,11 +168,9 @@ public class ContactSelectionListFragment extends Fragment
ContactSelectionListFragment.this.actionMode = null; ContactSelectionListFragment.this.actionMode = null;
getContactSelectionListAdapter().resetActionModeSelection(); getContactSelectionListAdapter().resetActionModeSelection();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { TypedArray color = getActivity().getTheme().obtainStyledAttributes(new int[]{android.R.attr.statusBarColor});
TypedArray color = getActivity().getTheme().obtainStyledAttributes(new int[] {android.R.attr.statusBarColor}); getActivity().getWindow().setStatusBarColor(color.getColor(0, Color.BLACK));
getActivity().getWindow().setStatusBarColor(color.getColor(0, Color.BLACK)); color.recycle();
color.recycle();
}
} }
}; };

View file

@ -940,12 +940,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
case AttachmentTypeSelector.TAKE_PHOTO: case AttachmentTypeSelector.TAKE_PHOTO:
attachmentManager.capturePhoto(this, TAKE_PHOTO); break; attachmentManager.capturePhoto(this, TAKE_PHOTO); break;
case AttachmentTypeSelector.RECORD_VIDEO: case AttachmentTypeSelector.RECORD_VIDEO:
if(VideoRecoder.canRecode()) { attachmentManager.captureVideo(this, RECORD_VIDEO);
attachmentManager.captureVideo(this, RECORD_VIDEO);
}
else {
Toast.makeText(this, "This device does not support video-compression (requires Android 4.4 KitKat)", Toast.LENGTH_LONG).show();
}
break; break;
} }
} }

View file

@ -893,11 +893,9 @@ public class ConversationFragment extends MessageSelectorFragment
mode.setTitle("1"); mode.setTitle("1");
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { Window window = getActivity().getWindow();
Window window = getActivity().getWindow(); statusBarColor = window.getStatusBarColor();
statusBarColor = window.getStatusBarColor(); window.setStatusBarColor(getResources().getColor(R.color.action_mode_status_bar));
window.setStatusBarColor(getResources().getColor(R.color.action_mode_status_bar));
}
setCorrectMenuVisibility(menu); setCorrectMenuVisibility(menu);
ConversationAdaptiveActionsToolbar.adjustMenuActions(menu, 10, requireActivity().getWindow().getDecorView().getMeasuredWidth()); ConversationAdaptiveActionsToolbar.adjustMenuActions(menu, 10, requireActivity().getWindow().getDecorView().getMeasuredWidth());
@ -914,9 +912,7 @@ public class ConversationFragment extends MessageSelectorFragment
((ConversationAdapter)list.getAdapter()).clearSelection(); ((ConversationAdapter)list.getAdapter()).clearSelection();
list.getAdapter().notifyDataSetChanged(); list.getAdapter().notifyDataSetChanged();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { getActivity().getWindow().setStatusBarColor(statusBarColor);
getActivity().getWindow().setStatusBarColor(statusBarColor);
}
actionMode = null; actionMode = null;
hideAddReactionView(); hideAddReactionView();

View file

@ -495,9 +495,7 @@ public class ConversationItem extends BaseConversationItem
audioViewStub.get().setAudio(new AudioSlide(context, messageRecord), duration); audioViewStub.get().setAudio(new AudioSlide(context, messageRecord), duration);
audioViewStub.get().setOnClickListener(passthroughClickListener); audioViewStub.get().setOnClickListener(passthroughClickListener);
audioViewStub.get().setOnLongClickListener(passthroughClickListener); audioViewStub.get().setOnLongClickListener(passthroughClickListener);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { audioViewStub.get().setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
audioViewStub.get().setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
}
ViewUtil.updateLayoutParams(bodyText, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); ViewUtil.updateLayoutParams(bodyText, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
ViewUtil.updateLayoutParams(groupSenderHolder, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); ViewUtil.updateLayoutParams(groupSenderHolder, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
@ -515,9 +513,7 @@ public class ConversationItem extends BaseConversationItem
documentViewStub.get().setDocument(new DocumentSlide(context, messageRecord)); documentViewStub.get().setDocument(new DocumentSlide(context, messageRecord));
documentViewStub.get().setDocumentClickListener(new ThumbnailClickListener()); documentViewStub.get().setDocumentClickListener(new ThumbnailClickListener());
documentViewStub.get().setOnLongClickListener(passthroughClickListener); documentViewStub.get().setOnLongClickListener(passthroughClickListener);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { documentViewStub.get().setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
documentViewStub.get().setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
}
ViewUtil.updateLayoutParams(bodyText, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); ViewUtil.updateLayoutParams(bodyText, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
ViewUtil.updateLayoutParams(groupSenderHolder, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); ViewUtil.updateLayoutParams(groupSenderHolder, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
@ -534,9 +530,7 @@ public class ConversationItem extends BaseConversationItem
webxdcViewStub.get().setWebxdc(messageRecord, context.getString(R.string.webxdc_app)); webxdcViewStub.get().setWebxdc(messageRecord, context.getString(R.string.webxdc_app));
webxdcViewStub.get().setWebxdcClickListener(new ThumbnailClickListener()); webxdcViewStub.get().setWebxdcClickListener(new ThumbnailClickListener());
webxdcViewStub.get().setOnLongClickListener(passthroughClickListener); webxdcViewStub.get().setOnLongClickListener(passthroughClickListener);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { webxdcViewStub.get().setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
webxdcViewStub.get().setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
}
ViewUtil.updateLayoutParams(bodyText, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); ViewUtil.updateLayoutParams(bodyText, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
ViewUtil.updateLayoutParams(groupSenderHolder, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); ViewUtil.updateLayoutParams(groupSenderHolder, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
@ -554,9 +548,7 @@ public class ConversationItem extends BaseConversationItem
vcardViewStub.get().setVcardClickListener(new ThumbnailClickListener()); vcardViewStub.get().setVcardClickListener(new ThumbnailClickListener());
vcardViewStub.get().setOnLongClickListener(passthroughClickListener); vcardViewStub.get().setOnLongClickListener(passthroughClickListener);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { vcardViewStub.get().setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
vcardViewStub.get().setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
}
ViewUtil.updateLayoutParams(bodyText, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); ViewUtil.updateLayoutParams(bodyText, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
ViewUtil.updateLayoutParams(groupSenderHolder, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); ViewUtil.updateLayoutParams(groupSenderHolder, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
@ -592,9 +584,7 @@ public class ConversationItem extends BaseConversationItem
mediaThumbnailStub.get().setOnLongClickListener(passthroughClickListener); mediaThumbnailStub.get().setOnLongClickListener(passthroughClickListener);
mediaThumbnailStub.get().setOnClickListener(passthroughClickListener); mediaThumbnailStub.get().setOnClickListener(passthroughClickListener);
mediaThumbnailStub.get().showShade(TextUtils.isEmpty(messageRecord.getText())); mediaThumbnailStub.get().showShade(TextUtils.isEmpty(messageRecord.getText()));
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { mediaThumbnailStub.get().setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
mediaThumbnailStub.get().setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
}
setThumbnailOutlineCorners(messageRecord, showSender); setThumbnailOutlineCorners(messageRecord, showSender);
@ -617,9 +607,7 @@ public class ConversationItem extends BaseConversationItem
stickerStub.get().setThumbnailClickListener(new StickerClickListener()); stickerStub.get().setThumbnailClickListener(new StickerClickListener());
stickerStub.get().setOnLongClickListener(passthroughClickListener); stickerStub.get().setOnLongClickListener(passthroughClickListener);
stickerStub.get().setOnClickListener(passthroughClickListener); stickerStub.get().setOnClickListener(passthroughClickListener);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { stickerStub.get().setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
stickerStub.get().setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
}
ViewUtil.updateLayoutParams(bodyText, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); ViewUtil.updateLayoutParams(bodyText, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
ViewUtil.updateLayoutParams(groupSenderHolder, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); ViewUtil.updateLayoutParams(groupSenderHolder, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);

View file

@ -174,9 +174,7 @@ class ConversationItemSwipeCallback extends ItemTouchHelper.SimpleCallback {
vibrate(viewHolder.itemView.getContext()); vibrate(viewHolder.itemView.getContext());
} }
} }
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { recyclerView.cancelPendingInputEvents();
recyclerView.cancelPendingInputEvents();
}
} }
private static void resetProgress(RecyclerView.ViewHolder viewHolder) { private static void resetProgress(RecyclerView.ViewHolder viewHolder) {
@ -199,11 +197,7 @@ class ConversationItemSwipeCallback extends ItemTouchHelper.SimpleCallback {
} }
private static float getSignFromDirection(@NonNull View view) { private static float getSignFromDirection(@NonNull View view) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { return view.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL ? -1f : 1f;
return view.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL ? -1f : 1f;
} else {
return 1f;
}
} }
private static boolean sameSign(float dX, float sign) { private static boolean sameSign(float dX, float sign) {

View file

@ -29,7 +29,6 @@ public class ConversationListItemInboxZero extends LinearLayout implements Binda
super(context, attrs, defStyleAttr); super(context, attrs, defStyleAttr);
} }
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public ConversationListItemInboxZero(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { public ConversationListItemInboxZero(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes); super(context, attrs, defStyleAttr, defStyleRes);
} }

View file

@ -197,12 +197,11 @@ public class LogViewFragment extends Fragment {
asMegs(info.maxMemory())); asMegs(info.maxMemory()));
} }
@TargetApi(VERSION_CODES.KITKAT)
public static String getMemoryClass(Context context) { public static String getMemoryClass(Context context) {
ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
String lowMem = ""; String lowMem = "";
if (VERSION.SDK_INT >= VERSION_CODES.KITKAT && activityManager.isLowRamDevice()) { if (activityManager.isLowRamDevice()) {
lowMem = ", low-mem device"; lowMem = ", low-mem device";
} }
return activityManager.getMemoryClass() + lowMem; return activityManager.getMemoryClass() + lowMem;
@ -252,10 +251,8 @@ public class LogViewFragment extends Fragment {
Locale locale = Util.getLocale(); Locale locale = Util.getLocale();
builder.append("lang=").append(locale.toString()).append("\n"); builder.append("lang=").append(locale.toString()).append("\n");
if (VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN_MR1) { boolean isRtl = Util.getLayoutDirection(context) == View.LAYOUT_DIRECTION_RTL;
boolean isRtl = Util.getLayoutDirection(context) == View.LAYOUT_DIRECTION_RTL; builder.append("rtl=").append(isRtl).append("\n");
builder.append("rtl=").append(isRtl).append("\n");
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
boolean notifPermGranted = PermissionChecker.checkSelfPermission(context, Manifest.permission.POST_NOTIFICATIONS) == PermissionChecker.PERMISSION_GRANTED; boolean notifPermGranted = PermissionChecker.checkSelfPermission(context, Manifest.permission.POST_NOTIFICATIONS) == PermissionChecker.PERMISSION_GRANTED;

View file

@ -228,11 +228,9 @@ public class ProfileDocumentsFragment
mode.getMenuInflater().inflate(R.menu.profile_context, menu); mode.getMenuInflater().inflate(R.menu.profile_context, menu);
mode.setTitle("1"); mode.setTitle("1");
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { Window window = getActivity().getWindow();
Window window = getActivity().getWindow(); originalStatusBarColor = window.getStatusBarColor();
originalStatusBarColor = window.getStatusBarColor(); window.setStatusBarColor(getResources().getColor(R.color.action_mode_status_bar));
window.setStatusBarColor(getResources().getColor(R.color.action_mode_status_bar));
}
setCorrectMenuVisibility(menu); setCorrectMenuVisibility(menu);
return true; return true;
} }
@ -282,9 +280,7 @@ public class ProfileDocumentsFragment
actionMode = null; actionMode = null;
getListAdapter().clearSelection(); getListAdapter().clearSelection();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { getActivity().getWindow().setStatusBarColor(originalStatusBarColor);
getActivity().getWindow().setStatusBarColor(originalStatusBarColor);
}
} }
} }
} }

View file

@ -219,11 +219,9 @@ public class ProfileGalleryFragment
mode.getMenuInflater().inflate(R.menu.profile_context, menu); mode.getMenuInflater().inflate(R.menu.profile_context, menu);
mode.setTitle("1"); mode.setTitle("1");
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { Window window = getActivity().getWindow();
Window window = getActivity().getWindow(); originalStatusBarColor = window.getStatusBarColor();
originalStatusBarColor = window.getStatusBarColor(); window.setStatusBarColor(getResources().getColor(R.color.action_mode_status_bar));
window.setStatusBarColor(getResources().getColor(R.color.action_mode_status_bar));
}
setCorrectMenuVisibility(menu); setCorrectMenuVisibility(menu);
return true; return true;
} }
@ -269,9 +267,7 @@ public class ProfileGalleryFragment
actionMode = null; actionMode = null;
getListAdapter().clearSelection(); getListAdapter().clearSelection();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { getActivity().getWindow().setStatusBarColor(originalStatusBarColor);
getActivity().getWindow().setStatusBarColor(originalStatusBarColor);
}
} }
} }
} }

View file

@ -268,11 +268,9 @@ public class ProfileSettingsFragment extends Fragment
menu.findItem(R.id.menu_select_all).setVisible(false); menu.findItem(R.id.menu_select_all).setVisible(false);
mode.setTitle("1"); mode.setTitle("1");
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { Window window = getActivity().getWindow();
Window window = getActivity().getWindow(); originalStatusBarColor = window.getStatusBarColor();
originalStatusBarColor = window.getStatusBarColor(); window.setStatusBarColor(getResources().getColor(R.color.action_mode_status_bar));
window.setStatusBarColor(getResources().getColor(R.color.action_mode_status_bar));
}
return true; return true;
} }
@ -314,9 +312,7 @@ public class ProfileSettingsFragment extends Fragment
public void onDestroyActionMode(ActionMode mode) { public void onDestroyActionMode(ActionMode mode) {
actionMode = null; actionMode = null;
adapter.clearSelection(); adapter.clearSelection();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { getActivity().getWindow().setStatusBarColor(originalStatusBarColor);
getActivity().getWindow().setStatusBarColor(originalStatusBarColor);
}
} }
} }

View file

@ -100,14 +100,10 @@ public class WebxdcActivity extends WebViewActivity implements DcEventCenter.DcE
public static void openWebxdcActivity(Context context, int msgId, boolean hideActionBar) { public static void openWebxdcActivity(Context context, int msgId, boolean hideActionBar) {
if (!Util.isClickedRecently()) { if (!Util.isClickedRecently()) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { if (Prefs.isDeveloperModeEnabled(context)) {
if (Prefs.isDeveloperModeEnabled(context)) { WebView.setWebContentsDebuggingEnabled(true);
WebView.setWebContentsDebuggingEnabled(true);
}
context.startActivity(getWebxdcIntent(context, msgId, hideActionBar));
} else {
Toast.makeText(context, "At least Android 5.0 (Lollipop) required for Webxdc.", Toast.LENGTH_LONG).show();
} }
context.startActivity(getWebxdcIntent(context, msgId, hideActionBar));
} }
} }
@ -329,7 +325,7 @@ public class WebxdcActivity extends WebViewActivity implements DcEventCenter.DcE
res = new WebResourceResponse("text/plain", "UTF-8", targetStream); res = new WebResourceResponse("text/plain", "UTF-8", targetStream);
} }
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && !internetAccess) { if (!internetAccess) {
Map<String, String> headers = new HashMap<>(); Map<String, String> headers = new HashMap<>();
headers.put("Content-Security-Policy", headers.put("Content-Security-Policy",
"default-src 'self'; " "default-src 'self'; "
@ -348,12 +344,10 @@ public class WebxdcActivity extends WebViewActivity implements DcEventCenter.DcE
} }
private void callJavaScriptFunction(String func) { private void callJavaScriptFunction(String func) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { if (internetAccess) {
if (internetAccess) { webView.evaluateJavascript("window." + func + ";", null);
webView.evaluateJavascript("window." + func + ";", null); } else {
} else { webView.evaluateJavascript("document.getElementById('frame').contentWindow." + func + ";", null);
webView.evaluateJavascript("document.getElementById('frame').contentWindow." + func + ";", null);
}
} }
} }

View file

@ -176,7 +176,7 @@ public class WelcomeActivity extends BaseActionBarActivity implements DcEventCen
.withPermanentDenialDialog(getString(R.string.perm_explain_access_to_storage_denied)) .withPermanentDenialDialog(getString(R.string.perm_explain_access_to_storage_denied))
.onAllGranted(() -> { .onAllGranted(() -> {
File imexDir = DcHelper.getImexDir(); File imexDir = DcHelper.getImexDir();
if (Build.VERSION.SDK_INT >= 30) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
AttachmentManager.selectMediaType(this, "application/x-tar", null, PICK_BACKUP, StorageUtil.getDownloadUri()); AttachmentManager.selectMediaType(this, "application/x-tar", null, PICK_BACKUP, StorageUtil.getDownloadUri());
} else { } else {
final String backupFile = dcContext.imexHasBackup(imexDir.getAbsolutePath()); final String backupFile = dcContext.imexHasBackup(imexDir.getAbsolutePath());

View file

@ -130,33 +130,23 @@ public class AttachmentTypeSelector extends PopupWindow {
public void onGlobalLayout() { public void onGlobalLayout() {
getContentView().getViewTreeObserver().removeGlobalOnLayoutListener(this); getContentView().getViewTreeObserver().removeGlobalOnLayoutListener(this);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { animateWindowInCircular(anchor, getContentView());
animateWindowInCircular(anchor, getContentView());
} else {
animateWindowInTranslate(getContentView());
}
} }
}); });
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { animateButtonIn(cameraButton, ANIMATION_DURATION / 2);
animateButtonIn(cameraButton, ANIMATION_DURATION / 2); animateButtonIn(videoButton, ANIMATION_DURATION / 2);
animateButtonIn(videoButton, ANIMATION_DURATION / 2); animateButtonIn(imageButton, ANIMATION_DURATION / 3);
animateButtonIn(imageButton, ANIMATION_DURATION / 3); animateButtonIn(contactButton, ANIMATION_DURATION / 3);
animateButtonIn(contactButton, ANIMATION_DURATION / 3); animateButtonIn(locationButton, ANIMATION_DURATION / 4);
animateButtonIn(locationButton, ANIMATION_DURATION / 4); animateButtonIn(documentButton, ANIMATION_DURATION / 4);
animateButtonIn(documentButton, ANIMATION_DURATION / 4); animateButtonIn(videoChatButton, 0);
animateButtonIn(videoChatButton, 0); animateButtonIn(closeButton, 0);
animateButtonIn(closeButton, 0);
}
} }
@Override @Override
public void dismiss() { public void dismiss() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { animateWindowOutCircular(currentAnchor, getContentView());
animateWindowOutCircular(currentAnchor, getContentView());
} else {
animateWindowOutTranslate(getContentView());
}
} }
public void setListener(@Nullable AttachmentClickedListener listener) { public void setListener(@Nullable AttachmentClickedListener listener) {
@ -186,7 +176,6 @@ public class AttachmentTypeSelector extends PopupWindow {
button.startAnimation(animation); button.startAnimation(animation);
} }
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
private void animateWindowInCircular(@Nullable View anchor, @NonNull View contentView) { private void animateWindowInCircular(@Nullable View anchor, @NonNull View contentView) {
Pair<Integer, Integer> coordinates = getClickOrigin(anchor, contentView); Pair<Integer, Integer> coordinates = getClickOrigin(anchor, contentView);
Animator animator = ViewAnimationUtils.createCircularReveal(contentView, Animator animator = ViewAnimationUtils.createCircularReveal(contentView,
@ -205,7 +194,6 @@ public class AttachmentTypeSelector extends PopupWindow {
getContentView().startAnimation(animation); getContentView().startAnimation(animation);
} }
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
private void animateWindowOutCircular(@Nullable View anchor, @NonNull View contentView) { private void animateWindowOutCircular(@Nullable View anchor, @NonNull View contentView) {
Pair<Integer, Integer> coordinates = getClickOrigin(anchor, contentView); Pair<Integer, Integer> coordinates = getClickOrigin(anchor, contentView);
Animator animator = ViewAnimationUtils.createCircularReveal(getContentView(), Animator animator = ViewAnimationUtils.createCircularReveal(getContentView(),

View file

@ -71,12 +71,10 @@ public class AudioView extends FrameLayout implements AudioSlidePlayer.Listener
this.pauseButton.setOnClickListener(new PauseClickedListener()); this.pauseButton.setOnClickListener(new PauseClickedListener());
this.seekBar.setOnSeekBarChangeListener(new SeekBarModifiedListener()); this.seekBar.setOnSeekBarChangeListener(new SeekBarModifiedListener());
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { this.playButton.setImageDrawable(context.getDrawable(R.drawable.play_icon));
this.playButton.setImageDrawable(context.getDrawable(R.drawable.play_icon)); this.pauseButton.setImageDrawable(context.getDrawable(R.drawable.pause_icon));
this.pauseButton.setImageDrawable(context.getDrawable(R.drawable.pause_icon)); this.playButton.setBackground(context.getDrawable(R.drawable.ic_circle_fill_white_48dp));
this.playButton.setBackground(context.getDrawable(R.drawable.ic_circle_fill_white_48dp)); this.pauseButton.setBackground(context.getDrawable(R.drawable.ic_circle_fill_white_48dp));
this.pauseButton.setBackground(context.getDrawable(R.drawable.ic_circle_fill_white_48dp));
}
setTint(getContext().getResources().getColor(R.color.audio_icon)); setTint(getContext().getResources().getColor(R.color.audio_icon));
} }
@ -192,13 +190,8 @@ public class AudioView extends FrameLayout implements AudioSlidePlayer.Listener
} }
public void setTint(int foregroundTint) { public void setTint(int foregroundTint) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { this.playButton.setBackgroundTintList(ColorStateList.valueOf(foregroundTint));
this.playButton.setBackgroundTintList(ColorStateList.valueOf(foregroundTint)); this.pauseButton.setBackgroundTintList(ColorStateList.valueOf(foregroundTint));
this.pauseButton.setBackgroundTintList(ColorStateList.valueOf(foregroundTint));
} else {
this.playButton.setColorFilter(foregroundTint, PorterDuff.Mode.SRC_IN);
this.pauseButton.setColorFilter(foregroundTint, PorterDuff.Mode.SRC_IN);
}
this.seekBar.getProgressDrawable().setColorFilter(foregroundTint, PorterDuff.Mode.SRC_IN); this.seekBar.getProgressDrawable().setColorFilter(foregroundTint, PorterDuff.Mode.SRC_IN);
@ -220,25 +213,20 @@ public class AudioView extends FrameLayout implements AudioSlidePlayer.Listener
private void togglePlayToPause() { private void togglePlayToPause() {
controlToggle.displayQuick(pauseButton); controlToggle.displayQuick(pauseButton);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { AnimatedVectorDrawable playToPauseDrawable = (AnimatedVectorDrawable) getContext().getDrawable(R.drawable.play_to_pause_animation);
AnimatedVectorDrawable playToPauseDrawable = (AnimatedVectorDrawable)getContext().getDrawable(R.drawable.play_to_pause_animation); pauseButton.setImageDrawable(playToPauseDrawable);
pauseButton.setImageDrawable(playToPauseDrawable); playToPauseDrawable.start();
playToPauseDrawable.start();
}
} }
private void togglePauseToPlay() { private void togglePauseToPlay() {
controlToggle.displayQuick(playButton); controlToggle.displayQuick(playButton);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { AnimatedVectorDrawable pauseToPlayDrawable = (AnimatedVectorDrawable) getContext().getDrawable(R.drawable.pause_to_play_animation);
AnimatedVectorDrawable pauseToPlayDrawable = (AnimatedVectorDrawable)getContext().getDrawable(R.drawable.pause_to_play_animation); playButton.setImageDrawable(pauseToPlayDrawable);
playButton.setImageDrawable(pauseToPlayDrawable); pauseToPlayDrawable.start();
pauseToPlayDrawable.start();
}
} }
private class PlayClickedListener implements View.OnClickListener { private class PlayClickedListener implements View.OnClickListener {
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
@Override @Override
public void onClick(View v) { public void onClick(View v) {
try { try {
@ -279,7 +267,6 @@ public class AudioView extends FrameLayout implements AudioSlidePlayer.Listener
} }
private class PauseClickedListener implements View.OnClickListener { private class PauseClickedListener implements View.OnClickListener {
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
@Override @Override
public void onClick(View v) { public void onClick(View v) {
Log.w(TAG, "pausebutton onClick"); Log.w(TAG, "pausebutton onClick");

View file

@ -122,7 +122,6 @@ public class ComposeText extends AppCompatEditText {
editorInfo.imeOptions &= ~EditorInfo.IME_FLAG_NO_ENTER_ACTION; editorInfo.imeOptions &= ~EditorInfo.IME_FLAG_NO_ENTER_ACTION;
} }
if (Build.VERSION.SDK_INT < 21) return inputConnection;
if (mediaListener == null) return inputConnection; if (mediaListener == null) return inputConnection;
if (inputConnection == null) return null; if (inputConnection == null) return null;

View file

@ -120,15 +120,10 @@ public class ConversationItemThumbnail extends FrameLayout {
@SuppressWarnings("SuspiciousNameCombination") @SuppressWarnings("SuspiciousNameCombination")
@Override @Override
protected void dispatchDraw(Canvas canvas) { protected void dispatchDraw(Canvas canvas) {
if (cornerMask.isLegacy()) {
cornerMask.mask(canvas);
}
super.dispatchDraw(canvas); super.dispatchDraw(canvas);
if (!cornerMask.isLegacy()) { cornerMask.mask(canvas);
cornerMask.mask(canvas);
}
final float halfStrokeWidth = outlinePaint.getStrokeWidth() / 2; final float halfStrokeWidth = outlinePaint.getStrokeWidth() / 2;

View file

@ -7,7 +7,7 @@ import android.graphics.Path;
import android.graphics.PorterDuff; import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode; import android.graphics.PorterDuffXfermode;
import android.graphics.RectF; import android.graphics.RectF;
import android.os.Build;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import android.view.View; import android.view.View;
@ -20,11 +20,7 @@ public class CornerMask {
private final RectF bounds = new RectF(); private final RectF bounds = new RectF();
public CornerMask(@NonNull View view) { public CornerMask(@NonNull View view) {
if (isLegacy()) { view.setLayerType(View.LAYER_TYPE_HARDWARE, null);
view.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
} else {
view.setLayerType(View.LAYER_TYPE_HARDWARE, null);
}
clearPaint.setColor(Color.BLACK); clearPaint.setColor(Color.BLACK);
clearPaint.setStyle(Paint.Style.FILL); clearPaint.setStyle(Paint.Style.FILL);
@ -44,19 +40,10 @@ public class CornerMask {
// Note: There's a bug in the P beta where most PorterDuff modes aren't working. But CLEAR does. // Note: There's a bug in the P beta where most PorterDuff modes aren't working. But CLEAR does.
// So we find and inverse path and use Mode.CLEAR for versions that support Path.op(). // So we find and inverse path and use Mode.CLEAR for versions that support Path.op().
// See issue https://issuetracker.google.com/issues/111394085. // See issue https://issuetracker.google.com/issues/111394085.
if (!isLegacy()) { outline.reset();
outline.reset(); outline.addRect(bounds, Path.Direction.CW);
outline.addRect(bounds, Path.Direction.CW); outline.op(corners, Path.Op.DIFFERENCE);
outline.op(corners, Path.Op.DIFFERENCE); canvas.drawPath(outline, clearPaint);
canvas.drawPath(outline, clearPaint);
} else {
corners.addRoundRect(bounds, radii, Path.Direction.CW);
canvas.clipPath(corners);
}
}
public boolean isLegacy() {
return Build.VERSION.SDK_INT < 19;
} }
public void setRadius(int radius) { public void setRadius(int radius) {

View file

@ -104,7 +104,7 @@ public class KeyboardAwareLinearLayout extends LinearLayoutCompat {
} }
private void updateKeyboardState() { private void updateKeyboardState() {
if (viewInset == 0 && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) viewInset = getViewInset(); if (viewInset == 0) viewInset = getViewInset();
getWindowVisibleDisplayFrame(rect); getWindowVisibleDisplayFrame(rect);
@ -148,7 +148,6 @@ public class KeyboardAwareLinearLayout extends LinearLayoutCompat {
} }
} }
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
private int getViewInset() { private int getViewInset() {
try { try {
Field attachInfoField = View.class.getDeclaredField("mAttachInfo"); Field attachInfoField = View.class.getDeclaredField("mAttachInfo");
@ -219,11 +218,7 @@ public class KeyboardAwareLinearLayout extends LinearLayoutCompat {
return Surface.ROTATION_0; return Surface.ROTATION_0;
} }
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
return ServiceUtil.getWindowManager(getContext()).getDefaultDisplay().getRotation();
}
if (Build.VERSION.SDK_INT >= 30) {
getContext().getDisplay().getRealMetrics(displayMetrics); getContext().getDisplay().getRealMetrics(displayMetrics);
} else { } else {
ServiceUtil.getWindowManager(getContext()).getDefaultDisplay().getRealMetrics(displayMetrics); ServiceUtil.getWindowManager(getContext()).getDefaultDisplay().getRealMetrics(displayMetrics);

View file

@ -40,7 +40,6 @@ public class MediaView extends FrameLayout {
initialize(); initialize();
} }
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public MediaView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) { public MediaView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes); super(context, attrs, defStyleAttr, defStyleRes);
initialize(); initialize();

View file

@ -78,7 +78,6 @@ public class QuoteView extends FrameLayout implements RecipientForeverObserver {
initialize(attrs); initialize(attrs);
} }
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public QuoteView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { public QuoteView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes); super(context, attrs, defStyleAttr, defStyleRes);
initialize(attrs); initialize(attrs);

View file

@ -29,7 +29,6 @@ public class RepeatableImageKey extends ImageButton {
init(); init();
} }
@TargetApi(VERSION_CODES.LOLLIPOP)
public RepeatableImageKey(Context context, AttributeSet attrs, int defStyleAttr, public RepeatableImageKey(Context context, AttributeSet attrs, int defStyleAttr,
int defStyleRes) int defStyleRes)
{ {

View file

@ -130,15 +130,11 @@ public class SearchToolbar extends LinearLayout {
searchItem.expandActionView(); searchItem.expandActionView();
if (Build.VERSION.SDK_INT >= 21) { Animator animator = ViewAnimationUtils.createCircularReveal(this, (int) x, (int) y, 0, getWidth());
Animator animator = ViewAnimationUtils.createCircularReveal(this, (int)x, (int)y, 0, getWidth()); animator.setDuration(400);
animator.setDuration(400);
setVisibility(View.VISIBLE); setVisibility(View.VISIBLE);
animator.start(); animator.start();
} else {
setVisibility(View.VISIBLE);
}
} }
} }
@ -153,19 +149,15 @@ public class SearchToolbar extends LinearLayout {
if (listener != null) listener.onSearchClosed(); if (listener != null) listener.onSearchClosed();
if (Build.VERSION.SDK_INT >= 21) { Animator animator = ViewAnimationUtils.createCircularReveal(this, (int) x, (int) y, getWidth(), 0);
Animator animator = ViewAnimationUtils.createCircularReveal(this, (int)x, (int)y, getWidth(), 0); animator.setDuration(400);
animator.setDuration(400); animator.addListener(new AnimationCompleteListener() {
animator.addListener(new AnimationCompleteListener() { @Override
@Override public void onAnimationEnd(Animator animation) {
public void onAnimationEnd(Animator animation) { setVisibility(View.INVISIBLE);
setVisibility(View.INVISIBLE); }
} });
}); animator.start();
animator.start();
} else {
setVisibility(View.INVISIBLE);
}
} }
} }

View file

@ -18,7 +18,6 @@ public class SwitchPreferenceCompat extends CheckBoxPreference {
setLayoutRes(); setLayoutRes();
} }
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public SwitchPreferenceCompat(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { public SwitchPreferenceCompat(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes); super(context, attrs, defStyleAttr, defStyleRes);
setLayoutRes(); setLayoutRes();

View file

@ -463,7 +463,7 @@ public class CameraView extends ViewGroup {
} }
final float newWidth = visibleRect.width() * scale; final float newWidth = visibleRect.width() * scale;
final float newHeight = visibleRect.height() * scale; final float newHeight = visibleRect.height() * scale;
final float centerX = (VERSION.SDK_INT < 14 || isTroublemaker()) ? previewWidth - newWidth / 2 : previewWidth / 2; final float centerX = isTroublemaker() ? previewWidth - newWidth / 2 : previewWidth / 2;
final float centerY = previewHeight / 2; final float centerY = previewHeight / 2;
visibleRect.set((int) (centerX - newWidth / 2), visibleRect.set((int) (centerX - newWidth / 2),

View file

@ -260,9 +260,7 @@ public class DcHelper {
} }
public static File getImexDir() { public static File getImexDir() {
// DIRECTORY_DOCUMENTS is only available since KitKat; // DIRECTORY_DOCUMENTS could be used but DIRECTORY_DOWNLOADS seems to be easier accessible by the user,
// as we also support Ice Cream Sandwich and Jellybean (2017: 11% in total), this is no option.
// Moreover, DIRECTORY_DOWNLOADS seems to be easier accessible by the user,
// eg. "Download Managers" are nearly always installed. // eg. "Download Managers" are nearly always installed.
// CAVE: do not use DownloadManager to add the file as it is deleted on uninstall then ... // CAVE: do not use DownloadManager to add the file as it is deleted on uninstall then ...
return Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS); return Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);

View file

@ -1,345 +0,0 @@
/*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will Google be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, as long as the origin is not misrepresented.
*/
package org.thoughtcrime.securesms.crypto;
import android.os.Build;
import android.os.Process;
import android.util.Log;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.security.NoSuchAlgorithmException;
import java.security.Provider;
import java.security.SecureRandom;
import java.security.SecureRandomSpi;
import java.security.Security;
/**
* This class is taken directly from the Android blog post announcing this bug:
* http://android-developers.blogspot.com/2013/08/some-securerandom-thoughts.html
*
* Since I still don't know exactly what the source of this bug was, I'm using
* this class verbatim under the assumption that the Android team knows what
* they're doing. Although, at this point, that is perhaps a foolish assumption.
*/
/**
* Fixes for the output of the default PRNG having low entropy.
*
* The fixes need to be applied via {@link #apply()} before any use of Java
* Cryptography Architecture primitives. A good place to invoke them is in the
* application's {@code onCreate}.
*/
public final class PRNGFixes {
private static final int VERSION_CODE_JELLY_BEAN = 16;
private static final int VERSION_CODE_JELLY_BEAN_MR2 = 18;
private static final byte[] BUILD_FINGERPRINT_AND_DEVICE_SERIAL =
getBuildFingerprintAndDeviceSerial();
/** Hidden constructor to prevent instantiation. */
private PRNGFixes() {}
/**
* Applies all fixes.
*
* @throws SecurityException if a fix is needed but could not be applied.
*/
public static void apply() {
applyOpenSSLFix();
installLinuxPRNGSecureRandom();
}
/**
* Applies the fix for OpenSSL PRNG having low entropy. Does nothing if the
* fix is not needed.
*
* @throws SecurityException if the fix is needed but could not be applied.
*/
private static void applyOpenSSLFix() throws SecurityException {
if ((Build.VERSION.SDK_INT < VERSION_CODE_JELLY_BEAN)
|| (Build.VERSION.SDK_INT > VERSION_CODE_JELLY_BEAN_MR2)) {
// No need to apply the fix
return;
}
try {
// Mix in the device- and invocation-specific seed.
Class.forName("org.apache.harmony.xnet.provider.jsse.NativeCrypto")
.getMethod("RAND_seed", byte[].class)
.invoke(null, generateSeed());
// Mix output of Linux PRNG into OpenSSL's PRNG
int bytesRead = (Integer) Class.forName(
"org.apache.harmony.xnet.provider.jsse.NativeCrypto")
.getMethod("RAND_load_file", String.class, long.class)
.invoke(null, "/dev/urandom", 1024);
if (bytesRead != 1024) {
throw new IOException(
"Unexpected number of bytes read from Linux PRNG: "
+ bytesRead);
}
} catch (Exception e) {
throw new SecurityException("Failed to seed OpenSSL PRNG", e);
}
}
/**
* Installs a Linux PRNG-backed {@code SecureRandom} implementation as the
* default. Does nothing if the implementation is already the default or if
* there is not need to install the implementation.
*
* @throws SecurityException if the fix is needed but could not be applied.
*/
private static void installLinuxPRNGSecureRandom()
throws SecurityException {
if (Build.VERSION.SDK_INT > VERSION_CODE_JELLY_BEAN_MR2) {
// No need to apply the fix
return;
}
// Install a Linux PRNG-based SecureRandom implementation as the
// default, if not yet installed.
Provider[] secureRandomProviders =
Security.getProviders("SecureRandom.SHA1PRNG");
if ((secureRandomProviders == null)
|| (secureRandomProviders.length < 1)
|| (!LinuxPRNGSecureRandomProvider.class.equals(
secureRandomProviders[0].getClass()))) {
Security.insertProviderAt(new LinuxPRNGSecureRandomProvider(), 1);
}
// Assert that new SecureRandom() and
// SecureRandom.getInstance("SHA1PRNG") return a SecureRandom backed
// by the Linux PRNG-based SecureRandom implementation.
SecureRandom rng1 = new SecureRandom();
if (!LinuxPRNGSecureRandomProvider.class.equals(
rng1.getProvider().getClass())) {
throw new SecurityException(
"new SecureRandom() backed by wrong Provider: "
+ rng1.getProvider().getClass());
}
SecureRandom rng2;
try {
rng2 = SecureRandom.getInstance("SHA1PRNG");
} catch (NoSuchAlgorithmException e) {
throw new SecurityException("SHA1PRNG not available", e);
}
if (!LinuxPRNGSecureRandomProvider.class.equals(
rng2.getProvider().getClass())) {
throw new SecurityException(
"SecureRandom.getInstance(\"SHA1PRNG\") backed by wrong"
+ " Provider: " + rng2.getProvider().getClass());
}
}
/**
* {@code Provider} of {@code SecureRandom} engines which pass through
* all requests to the Linux PRNG.
*/
private static class LinuxPRNGSecureRandomProvider extends Provider {
public LinuxPRNGSecureRandomProvider() {
super("LinuxPRNG",
1.0,
"A Linux-specific random number provider that uses"
+ " /dev/urandom");
// Although /dev/urandom is not a SHA-1 PRNG, some apps
// explicitly request a SHA1PRNG SecureRandom and we thus need to
// prevent them from getting the default implementation whose output
// may have low entropy.
put("SecureRandom.SHA1PRNG", LinuxPRNGSecureRandom.class.getName());
put("SecureRandom.SHA1PRNG ImplementedIn", "Software");
}
}
/**
* {@link SecureRandomSpi} which passes all requests to the Linux PRNG
* ({@code /dev/urandom}).
*/
public static class LinuxPRNGSecureRandom extends SecureRandomSpi {
/*
* IMPLEMENTATION NOTE: Requests to generate bytes and to mix in a seed
* are passed through to the Linux PRNG (/dev/urandom). Instances of
* this class seed themselves by mixing in the current time, PID, UID,
* build fingerprint, and hardware serial number (where available) into
* Linux PRNG.
*
* Concurrency: Read requests to the underlying Linux PRNG are
* serialized (on sLock) to ensure that multiple threads do not get
* duplicated PRNG output.
*/
private static final File URANDOM_FILE = new File("/dev/urandom");
private static final Object sLock = new Object();
/**
* Input stream for reading from Linux PRNG or {@code null} if not yet
* opened.
*
* @GuardedBy("sLock")
*/
private static DataInputStream sUrandomIn;
/**
* Output stream for writing to Linux PRNG or {@code null} if not yet
* opened.
*
* @GuardedBy("sLock")
*/
private static OutputStream sUrandomOut;
/**
* Whether this engine instance has been seeded. This is needed because
* each instance needs to seed itself if the client does not explicitly
* seed it.
*/
private boolean mSeeded;
@Override
protected void engineSetSeed(byte[] bytes) {
try {
OutputStream out;
synchronized (sLock) {
out = getUrandomOutputStream();
}
out.write(bytes);
out.flush();
} catch (IOException e) {
// On a small fraction of devices /dev/urandom is not writable.
// Log and ignore.
Log.w(PRNGFixes.class.getSimpleName(),
"Failed to mix seed into " + URANDOM_FILE);
} finally {
mSeeded = true;
}
}
@Override
protected void engineNextBytes(byte[] bytes) {
if (!mSeeded) {
// Mix in the device- and invocation-specific seed.
engineSetSeed(generateSeed());
}
try {
DataInputStream in;
synchronized (sLock) {
in = getUrandomInputStream();
}
synchronized (in) {
in.readFully(bytes);
}
} catch (IOException e) {
throw new SecurityException(
"Failed to read from " + URANDOM_FILE, e);
}
}
@Override
protected byte[] engineGenerateSeed(int size) {
byte[] seed = new byte[size];
engineNextBytes(seed);
return seed;
}
private DataInputStream getUrandomInputStream() {
synchronized (sLock) {
if (sUrandomIn == null) {
// NOTE: Consider inserting a BufferedInputStream between
// DataInputStream and FileInputStream if you need higher
// PRNG output performance and can live with future PRNG
// output being pulled into this process prematurely.
try {
sUrandomIn = new DataInputStream(
new FileInputStream(URANDOM_FILE));
} catch (IOException e) {
throw new SecurityException("Failed to open "
+ URANDOM_FILE + " for reading", e);
}
}
return sUrandomIn;
}
}
private OutputStream getUrandomOutputStream() throws IOException {
synchronized (sLock) {
if (sUrandomOut == null) {
sUrandomOut = new FileOutputStream(URANDOM_FILE);
}
return sUrandomOut;
}
}
}
/**
* Generates a device- and invocation-specific seed to be mixed into the
* Linux PRNG.
*/
private static byte[] generateSeed() {
try {
ByteArrayOutputStream seedBuffer = new ByteArrayOutputStream();
DataOutputStream seedBufferOut =
new DataOutputStream(seedBuffer);
seedBufferOut.writeLong(System.currentTimeMillis());
seedBufferOut.writeLong(System.nanoTime());
seedBufferOut.writeInt(Process.myPid());
seedBufferOut.writeInt(Process.myUid());
seedBufferOut.write(BUILD_FINGERPRINT_AND_DEVICE_SERIAL);
seedBufferOut.close();
return seedBuffer.toByteArray();
} catch (IOException e) {
throw new SecurityException("Failed to generate seed", e);
}
}
/**
* Gets the hardware serial number of this device.
*
* @return serial number or {@code null} if not available.
*/
private static String getDeviceSerialNumber() {
// We're using the Reflection API because Build.SERIAL is only available
// since API Level 9 (Gingerbread, Android 2.3).
try {
return (String) Build.class.getField("SERIAL").get(null);
} catch (Exception ignored) {
return null;
}
}
private static byte[] getBuildFingerprintAndDeviceSerial() {
StringBuilder result = new StringBuilder();
String fingerprint = Build.FINGERPRINT;
if (fingerprint != null) {
result.append(fingerprint);
}
String serial = getDeviceSerialNumber();
if (serial != null) {
result.append(serial);
}
try {
return result.toString().getBytes("UTF-8");
} catch (UnsupportedEncodingException e) {
throw new RuntimeException("UTF-8 encoding not supported");
}
}
}

View file

@ -585,7 +585,7 @@ public class AttachmentManager {
final Intent intent = new Intent(); final Intent intent = new Intent();
intent.setType(type); intent.setType(type);
if (extraMimeType != null && Build.VERSION.SDK_INT >= 19) { if (extraMimeType != null) {
intent.putExtra(Intent.EXTRA_MIME_TYPES, extraMimeType); intent.putExtra(Intent.EXTRA_MIME_TYPES, extraMimeType);
} }
@ -597,14 +597,12 @@ public class AttachmentManager {
intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true); intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
} }
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { intent.setAction(Intent.ACTION_OPEN_DOCUMENT);
intent.setAction(Intent.ACTION_OPEN_DOCUMENT); try {
try { activity.startActivityForResult(intent, requestCode);
activity.startActivityForResult(intent, requestCode); return;
return; } catch (ActivityNotFoundException anfe) {
} catch (ActivityNotFoundException anfe) { Log.w(TAG, "couldn't complete ACTION_OPEN_DOCUMENT, no activity found. falling back.");
Log.w(TAG, "couldn't complete ACTION_OPEN_DOCUMENT, no activity found. falling back.");
}
} }
intent.setAction(Intent.ACTION_GET_CONTENT); intent.setAction(Intent.ACTION_GET_CONTENT);

View file

@ -187,9 +187,7 @@ public class AdvancedPreferenceFragment extends ListSummaryPreferenceFragment
Preference developerModeEnabled = this.findPreference("pref_developer_mode_enabled"); Preference developerModeEnabled = this.findPreference("pref_developer_mode_enabled");
developerModeEnabled.setOnPreferenceChangeListener((preference, newValue) -> { developerModeEnabled.setOnPreferenceChangeListener((preference, newValue) -> {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { WebView.setWebContentsDebuggingEnabled((Boolean) newValue);
WebView.setWebContentsDebuggingEnabled((Boolean) newValue);
}
return true; return true;
}); });

View file

@ -26,7 +26,6 @@ public class ProfilePreference extends Preference {
private TextView profileNameView; private TextView profileNameView;
private TextView profileAddressView; private TextView profileAddressView;
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public ProfilePreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { public ProfilePreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes); super(context, attrs, defStyleAttr, defStyleRes);
initialize(); initialize();

View file

@ -63,15 +63,10 @@ public class AvatarHelper {
} }
public static void cropAvatar(Activity context, Uri imageUri) { public static void cropAvatar(Activity context, Uri imageUri) {
if (Build.VERSION.SDK_INT >= 19) { // Image editor requires Android 4.4 KitKat or newer. Intent intent = new Intent(context, ScribbleActivity.class);
Intent intent = new Intent(context, ScribbleActivity.class); intent.setData(imageUri);
intent.setData(imageUri); intent.putExtra(ScribbleActivity.CROP_AVATAR, true);
intent.putExtra(ScribbleActivity.CROP_AVATAR, true); context.startActivityForResult(intent, ScribbleActivity.SCRIBBLE_REQUEST_CODE);
context.startActivityForResult(intent, ScribbleActivity.SCRIBBLE_REQUEST_CODE);
} else {
Uri outputFile = Uri.fromFile(new File(context.getCacheDir(), "cropped"));
Crop.of(imageUri, outputFile).asSquare().start(context);
}
} }
} }

View file

@ -59,9 +59,6 @@ public class AddReactionView extends LinearLayout {
} }
anyReactionView = findViewById(R.id.reaction_any); anyReactionView = findViewById(R.id.reaction_any);
anyReactionView.setOnClickListener(v -> anyReactionClicked()); anyReactionView.setOnClickListener(v -> anyReactionClicked());
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
anyReactionView.setVisibility(View.GONE); // EmojiPickerView requires SDK 21 or newer
}
} }
} }

View file

@ -96,11 +96,7 @@ public final class ImageEditorHud extends LinearLayout {
} }
private void initializeVisibilityMap() { private void initializeVisibilityMap() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { setVisibleViewsWhenInMode(Mode.NONE, drawButton, highlightButton, blurButton, textButton, stickerButton, cropButton, undoButton, saveButton);
setVisibleViewsWhenInMode(Mode.NONE, drawButton, highlightButton, blurButton, textButton, stickerButton, cropButton, undoButton, saveButton);
} else {
setVisibleViewsWhenInMode(Mode.NONE, drawButton, highlightButton, textButton, stickerButton, cropButton, undoButton, saveButton);
}
setVisibleViewsWhenInMode(Mode.DRAW, confirmButton, undoButton, colorPicker, colorPalette); setVisibleViewsWhenInMode(Mode.DRAW, confirmButton, undoButton, colorPicker, colorPalette);

View file

@ -117,16 +117,13 @@ final class UriGlideRenderer implements Renderer {
rendererContext.restore(); rendererContext.restore();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { renderBlurOverlay(rendererContext);
renderBlurOverlay(rendererContext);
}
} else if (rendererContext.isBlockingLoad()) { } else if (rendererContext.isBlockingLoad()) {
// If failed to load, we draw a black out, in case image was sticker positioned to cover private info. // If failed to load, we draw a black out, in case image was sticker positioned to cover private info.
rendererContext.canvas.drawRect(Bounds.FULL_BOUNDS, paint); rendererContext.canvas.drawRect(Bounds.FULL_BOUNDS, paint);
} }
} }
@RequiresApi(17)
private void renderBlurOverlay(RendererContext rendererContext) { private void renderBlurOverlay(RendererContext rendererContext) {
boolean renderMask = false; boolean renderMask = false;

View file

@ -98,7 +98,6 @@ public class VerticalSlideColorPicker extends View {
init(); init();
} }
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public VerticalSlideColorPicker(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { public VerticalSlideColorPicker(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes); super(context, attrs, defStyleAttr, defStyleRes);
init(); init();

View file

@ -15,10 +15,6 @@ public final class AccessibilityUtil {
Log.e("AccessibilityUtil", "animationsDisabled: context was null"); Log.e("AccessibilityUtil", "animationsDisabled: context was null");
return false; return false;
} }
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { return Settings.Global.getFloat(context.getContentResolver(), Settings.Global.ANIMATOR_DURATION_SCALE, 1) == 0f;
return Settings.Global.getFloat(context.getContentResolver(), Settings.Global.ANIMATOR_DURATION_SCALE, 1) == 0f;
} else {
return false;
}
} }
} }

View file

@ -110,11 +110,7 @@ public class DateUtils extends android.text.format.DateUtils {
} }
private static String getLocalizedPattern(String template) { private static String getLocalizedPattern(String template) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) { return DateFormat.getBestDateTimePattern(Util.getLocale(), template);
return DateFormat.getBestDateTimePattern(Util.getLocale(), template);
} else {
return new SimpleDateFormat(template, Util.getLocale()).toLocalizedPattern();
}
} }
public static String getFormatedDuration(long millis) { public static String getFormatedDuration(long millis) {

View file

@ -16,8 +16,7 @@ public class FileProviderUtil {
private static final String AUTHORITY = BuildConfig.APPLICATION_ID+".fileprovider"; private static final String AUTHORITY = BuildConfig.APPLICATION_ID+".fileprovider";
public static Uri getUriFor(@NonNull Context context, @NonNull File file) throws IllegalStateException, NullPointerException { public static Uri getUriFor(@NonNull Context context, @NonNull File file) throws IllegalStateException, NullPointerException {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) return FileProvider.getUriForFile(context, AUTHORITY, file); return FileProvider.getUriForFile(context, AUTHORITY, file);
else return Uri.fromFile(file);
} }
} }

View file

@ -12,7 +12,7 @@ public class ScreenLockUtil {
public static boolean applyScreenLock(Activity activity, String title, String descr, int requestCode) { public static boolean applyScreenLock(Activity activity, String title, String descr, int requestCode) {
KeyguardManager keyguardManager = (KeyguardManager) activity.getSystemService(Context.KEYGUARD_SERVICE); KeyguardManager keyguardManager = (KeyguardManager) activity.getSystemService(Context.KEYGUARD_SERVICE);
Intent intent; Intent intent;
if (keyguardManager != null && isScreenLockAvailable()) { if (keyguardManager != null) {
intent = keyguardManager.createConfirmDeviceCredentialIntent(title, descr); intent = keyguardManager.createConfirmDeviceCredentialIntent(title, descr);
if (intent != null) { if (intent != null) {
activity.startActivityForResult(intent, requestCode); activity.startActivityForResult(intent, requestCode);
@ -22,7 +22,4 @@ public class ScreenLockUtil {
return false; return false;
} }
private static boolean isScreenLockAvailable() {
return android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP;
}
} }

View file

@ -20,28 +20,16 @@ public class StorageUtil {
} }
public static @NonNull Uri getVideoUri() { public static @NonNull Uri getVideoUri() {
if (Build.VERSION.SDK_INT < 21) { return MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
return getLegacyUri(Environment.DIRECTORY_MOVIES);
} else {
return MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
}
} }
public static @NonNull public static @NonNull
Uri getAudioUri() { Uri getAudioUri() {
if (Build.VERSION.SDK_INT < 21) { return MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
return getLegacyUri(Environment.DIRECTORY_MUSIC);
} else {
return MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
}
} }
public static @NonNull Uri getImageUri() { public static @NonNull Uri getImageUri() {
if (Build.VERSION.SDK_INT < 21) { return MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
return getLegacyUri(Environment.DIRECTORY_PICTURES);
} else {
return MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
}
} }
public static @NonNull Uri getDownloadUri() { public static @NonNull Uri getDownloadUri() {

View file

@ -257,12 +257,10 @@ public class Util {
return Arrays.hashCode(objects); return Arrays.hashCode(objects);
} }
@TargetApi(VERSION_CODES.KITKAT)
public static boolean isLowMemory(Context context) { public static boolean isLowMemory(Context context) {
ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
return (VERSION.SDK_INT >= VERSION_CODES.KITKAT && activityManager.isLowRamDevice()) || return activityManager.isLowRamDevice() || activityManager.getLargeMemoryClass() <= 64;
activityManager.getLargeMemoryClass() <= 64;
} }
public static int clamp(int value, int min, int max) { public static int clamp(int value, int min, int max) {
@ -386,10 +384,7 @@ public class Util {
} }
public static int getLayoutDirection(Context context) { public static int getLayoutDirection(Context context) {
if (VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN_MR1) { Configuration configuration = context.getResources().getConfiguration();
Configuration configuration = context.getResources().getConfiguration(); return configuration.getLayoutDirection();
return configuration.getLayoutDirection();
}
return ViewCompat.LAYOUT_DIRECTION_LTR;
} }
} }

View file

@ -168,18 +168,15 @@ public class ViewUtil {
@SuppressLint("RtlHardcoded") @SuppressLint("RtlHardcoded")
public static void setTextViewGravityStart(final @NonNull TextView textView, @NonNull Context context) { public static void setTextViewGravityStart(final @NonNull TextView textView, @NonNull Context context) {
if (VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN_MR1) { if (Util.getLayoutDirection(context) == View.LAYOUT_DIRECTION_RTL) {
if (Util.getLayoutDirection(context) == View.LAYOUT_DIRECTION_RTL) { textView.setGravity(Gravity.RIGHT);
textView.setGravity(Gravity.RIGHT); } else {
} else { textView.setGravity(Gravity.LEFT);
textView.setGravity(Gravity.LEFT);
}
} }
} }
public static void mirrorIfRtl(View view, Context context) { public static void mirrorIfRtl(View view, Context context) {
if (VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN_MR1 && if (Util.getLayoutDirection(context) == View.LAYOUT_DIRECTION_RTL) {
Util.getLayoutDirection(context) == View.LAYOUT_DIRECTION_RTL) {
view.setScaleX(-1.0f); view.setScaleX(-1.0f);
} }
} }

View file

@ -1,14 +1,10 @@
package org.thoughtcrime.securesms.video.recode; package org.thoughtcrime.securesms.video.recode;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.content.Context; import android.content.Context;
import android.media.MediaCodec; import android.media.MediaCodec;
import android.media.MediaCodecInfo; import android.media.MediaCodecInfo;
import android.media.MediaCodecList;
import android.media.MediaExtractor; import android.media.MediaExtractor;
import android.media.MediaFormat; import android.media.MediaFormat;
import android.os.Build;
import android.util.Log; import android.util.Log;
import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AlertDialog;
@ -36,14 +32,7 @@ public class VideoRecoder {
private static final String TAG = VideoRecoder.class.getSimpleName(); private static final String TAG = VideoRecoder.class.getSimpleName();
private boolean videoConvertFirstWrite = true;
private final static String MIME_TYPE = "video/avc"; private final static String MIME_TYPE = "video/avc";
private final static int PROCESSOR_TYPE_OTHER = 0;
private final static int PROCESSOR_TYPE_QCOM = 1;
private final static int PROCESSOR_TYPE_INTEL = 2;
private final static int PROCESSOR_TYPE_MTK = 3;
private final static int PROCESSOR_TYPE_SEC = 4;
private final static int PROCESSOR_TYPE_TI = 5;
private final boolean cancelCurrentVideoConversion = false; private final boolean cancelCurrentVideoConversion = false;
private final Object videoConvertSync = new Object(); private final Object videoConvertSync = new Object();
@ -57,7 +46,6 @@ public class VideoRecoder {
} }
} }
@TargetApi(16)
private int selectTrack(MediaExtractor extractor, boolean audio) { private int selectTrack(MediaExtractor extractor, boolean audio) {
int numTracks = extractor.getTrackCount(); int numTracks = extractor.getTrackCount();
for (int i = 0; i < numTracks; i++) { for (int i = 0; i < numTracks; i++) {
@ -76,60 +64,6 @@ public class VideoRecoder {
return -5; return -5;
} }
@SuppressLint("NewApi")
private static MediaCodecInfo selectCodec(String mimeType) {
int numCodecs = MediaCodecList.getCodecCount();
MediaCodecInfo lastCodecInfo = null;
for (int i = 0; i < numCodecs; i++) {
MediaCodecInfo codecInfo = MediaCodecList.getCodecInfoAt(i);
if (!codecInfo.isEncoder()) {
continue;
}
String[] types = codecInfo.getSupportedTypes();
for (String type : types) {
if (type.equalsIgnoreCase(mimeType)) {
lastCodecInfo = codecInfo;
if (!lastCodecInfo.getName().equals("OMX.SEC.avc.enc")) {
return lastCodecInfo;
} else if (lastCodecInfo.getName().equals("OMX.SEC.AVC.Encoder")) {
return lastCodecInfo;
}
}
}
}
return lastCodecInfo;
}
private static boolean isRecognizedFormat(int colorFormat) {
switch (colorFormat) {
case MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Planar:
case MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420PackedPlanar:
case MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420SemiPlanar:
case MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420PackedSemiPlanar:
case MediaCodecInfo.CodecCapabilities.COLOR_TI_FormatYUV420PackedSemiPlanar:
return true;
default:
return false;
}
}
@SuppressLint("NewApi")
private static int selectColorFormat(MediaCodecInfo codecInfo, String mimeType) {
MediaCodecInfo.CodecCapabilities capabilities = codecInfo.getCapabilitiesForType(mimeType);
int lastColorFormat = 0;
for (int i = 0; i < capabilities.colorFormats.length; i++) {
int colorFormat = capabilities.colorFormats[i];
if (isRecognizedFormat(colorFormat)) {
lastColorFormat = colorFormat;
if (!(codecInfo.getName().equals("OMX.SEC.AVC.Encoder") && colorFormat == 19)) {
return colorFormat;
}
}
}
return lastColorFormat;
}
@TargetApi(16)
private long readAndWriteTrack(MediaExtractor extractor, MP4Builder mediaMuxer, MediaCodec.BufferInfo info, long start, long end, File file, boolean isAudio) throws Exception { private long readAndWriteTrack(MediaExtractor extractor, MP4Builder mediaMuxer, MediaCodec.BufferInfo info, long start, long end, File file, boolean isAudio) throws Exception {
int trackIndex = selectTrack(extractor, isAudio); int trackIndex = selectTrack(extractor, isAudio);
if (trackIndex >= 0) { if (trackIndex >= 0) {
@ -199,7 +133,6 @@ public class VideoRecoder {
return -1; return -1;
} }
@TargetApi(16)
private boolean convertVideo(final VideoEditedInfo videoEditedInfo, String destPath) { private boolean convertVideo(final VideoEditedInfo videoEditedInfo, String destPath) {
long startTime = videoEditedInfo.startTime; long startTime = videoEditedInfo.startTime;
@ -214,29 +147,21 @@ public class VideoRecoder {
int rotateRender = 0; int rotateRender = 0;
File cacheFile = new File(destPath); File cacheFile = new File(destPath);
if (Build.VERSION.SDK_INT < 18 && resultHeight > resultWidth && resultWidth != originalWidth && resultHeight != originalHeight) { if (rotationValue == 90) {
int temp = resultHeight; int temp = resultHeight;
resultHeight = resultWidth; resultHeight = resultWidth;
resultWidth = temp; resultWidth = temp;
rotationValue = 90; rotationValue = 0;
rotateRender = 270; rotateRender = 270;
} else if (Build.VERSION.SDK_INT > 20) { } else if (rotationValue == 180) {
if (rotationValue == 90) { rotateRender = 180;
int temp = resultHeight; rotationValue = 0;
resultHeight = resultWidth; } else if (rotationValue == 270) {
resultWidth = temp; int temp = resultHeight;
rotationValue = 0; resultHeight = resultWidth;
rotateRender = 270; resultWidth = temp;
} else if (rotationValue == 180) { rotationValue = 0;
rotateRender = 180; rotateRender = 90;
rotationValue = 0;
} else if (rotationValue == 270) {
int temp = resultHeight;
resultHeight = resultWidth;
resultWidth = temp;
rotationValue = 0;
rotateRender = 90;
}
} }
File inputFile = new File(videoEditedInfo.originalPath); File inputFile = new File(videoEditedInfo.originalPath);
@ -246,7 +171,6 @@ public class VideoRecoder {
return false; return false;
} }
videoConvertFirstWrite = true;
boolean error = false; boolean error = false;
long videoStartTime = startTime; long videoStartTime = startTime;
@ -282,71 +206,12 @@ public class VideoRecoder {
boolean outputDone = false; boolean outputDone = false;
boolean inputDone = false; boolean inputDone = false;
boolean decoderDone = false; boolean decoderDone = false;
int swapUV = 0;
int videoTrackIndex = -5; int videoTrackIndex = -5;
int colorFormat; int colorFormat;
int processorType = PROCESSOR_TYPE_OTHER; colorFormat = MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface;
String manufacturer = Build.MANUFACTURER.toLowerCase();
if (Build.VERSION.SDK_INT < 18) {
MediaCodecInfo codecInfo = selectCodec(MIME_TYPE);
colorFormat = selectColorFormat(codecInfo, MIME_TYPE);
if (colorFormat == 0) {
throw new RuntimeException("no supported color format");
}
String codecName = codecInfo.getName();
if (codecName.contains("OMX.qcom.")) {
processorType = PROCESSOR_TYPE_QCOM;
if (Build.VERSION.SDK_INT == 16) {
if (manufacturer.equals("lge") || manufacturer.equals("nokia")) {
swapUV = 1;
}
}
} else if (codecName.contains("OMX.Intel.")) {
processorType = PROCESSOR_TYPE_INTEL;
} else if (codecName.equals("OMX.MTK.VIDEO.ENCODER.AVC")) {
processorType = PROCESSOR_TYPE_MTK;
} else if (codecName.equals("OMX.SEC.AVC.Encoder")) {
processorType = PROCESSOR_TYPE_SEC;
swapUV = 1;
} else if (codecName.equals("OMX.TI.DUCATI1.VIDEO.H264E")) {
processorType = PROCESSOR_TYPE_TI;
}
//Log.i("DeltaChat", "codec = " + codecInfo.getName() + " manufacturer = " + manufacturer + "device = " + Build.MODEL);
} else {
colorFormat = MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface;
}
//Log.i("DeltaChat", "colorFormat = " + colorFormat); //Log.i("DeltaChat", "colorFormat = " + colorFormat);
int resultHeightAligned = resultHeight;
int padding = 0;
int bufferSize = resultWidth * resultHeight * 3 / 2;
if (processorType == PROCESSOR_TYPE_OTHER) {
if (resultHeight % 16 != 0) {
resultHeightAligned += (16 - (resultHeight % 16));
padding = resultWidth * (resultHeightAligned - resultHeight);
bufferSize += padding * 5 / 4;
}
} else if (processorType == PROCESSOR_TYPE_QCOM) {
if (!manufacturer.toLowerCase().equals("lge")) {
int uvoffset = (resultWidth * resultHeight + 2047) & ~2047;
padding = uvoffset - (resultWidth * resultHeight);
bufferSize += padding;
}
} else if (processorType == PROCESSOR_TYPE_TI) {
//resultHeightAligned = 368;
//bufferSize = resultWidth * resultHeightAligned * 3 / 2;
//resultHeightAligned += (16 - (resultHeight % 16));
//padding = resultWidth * (resultHeightAligned - resultHeight);
//bufferSize += padding * 5 / 4;
} else if (processorType == PROCESSOR_TYPE_MTK) {
if (manufacturer.equals("baidu")) {
resultHeightAligned += (16 - (resultHeight % 16));
padding = resultWidth * (resultHeightAligned - resultHeight);
bufferSize += padding * 5 / 4;
}
}
extractor.selectTrack(videoIndex); extractor.selectTrack(videoIndex);
if (startTime > 0) { if (startTime > 0) {
extractor.seekTo(startTime, MediaExtractor.SEEK_TO_PREVIOUS_SYNC); extractor.seekTo(startTime, MediaExtractor.SEEK_TO_PREVIOUS_SYNC);
@ -360,39 +225,21 @@ public class VideoRecoder {
outputFormat.setInteger(MediaFormat.KEY_BIT_RATE, resultVideoBitrate != 0 ? resultVideoBitrate : 921600); outputFormat.setInteger(MediaFormat.KEY_BIT_RATE, resultVideoBitrate != 0 ? resultVideoBitrate : 921600);
outputFormat.setInteger(MediaFormat.KEY_FRAME_RATE, 25); outputFormat.setInteger(MediaFormat.KEY_FRAME_RATE, 25);
outputFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 10); outputFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 10);
if (Build.VERSION.SDK_INT < 18) {
outputFormat.setInteger("stride", resultWidth + 32);
outputFormat.setInteger("slice-height", resultHeight);
}
encoder = MediaCodec.createEncoderByType(MIME_TYPE); encoder = MediaCodec.createEncoderByType(MIME_TYPE);
encoder.configure(outputFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE); encoder.configure(outputFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
if (Build.VERSION.SDK_INT >= 18) { inputSurface = new InputSurface(encoder.createInputSurface());
inputSurface = new InputSurface(encoder.createInputSurface()); inputSurface.makeCurrent();
inputSurface.makeCurrent();
}
encoder.start(); encoder.start();
decoder = MediaCodec.createDecoderByType(inputFormat.getString(MediaFormat.KEY_MIME)); decoder = MediaCodec.createDecoderByType(inputFormat.getString(MediaFormat.KEY_MIME));
if (Build.VERSION.SDK_INT >= 18) { outputSurface = new OutputSurface();
outputSurface = new OutputSurface();
} else {
outputSurface = new OutputSurface(resultWidth, resultHeight, rotateRender);
}
decoder.configure(inputFormat, outputSurface.getSurface(), null, 0); decoder.configure(inputFormat, outputSurface.getSurface(), null, 0);
decoder.start(); decoder.start();
final int TIMEOUT_USEC = 2500; final int TIMEOUT_USEC = 2500;
ByteBuffer[] decoderInputBuffers = null; ByteBuffer[] decoderInputBuffers = null;
ByteBuffer[] encoderOutputBuffers = null; ByteBuffer[] encoderOutputBuffers = null;
ByteBuffer[] encoderInputBuffers = null;
if (Build.VERSION.SDK_INT < 21) {
decoderInputBuffers = decoder.getInputBuffers();
encoderOutputBuffers = encoder.getOutputBuffers();
if (Build.VERSION.SDK_INT < 18) {
encoderInputBuffers = encoder.getInputBuffers();
}
}
checkConversionCanceled(); checkConversionCanceled();
@ -405,11 +252,7 @@ public class VideoRecoder {
int inputBufIndex = decoder.dequeueInputBuffer(TIMEOUT_USEC); int inputBufIndex = decoder.dequeueInputBuffer(TIMEOUT_USEC);
if (inputBufIndex >= 0) { if (inputBufIndex >= 0) {
ByteBuffer inputBuf; ByteBuffer inputBuf;
if (Build.VERSION.SDK_INT < 21) { inputBuf = decoder.getInputBuffer(inputBufIndex);
inputBuf = decoderInputBuffers[inputBufIndex];
} else {
inputBuf = decoder.getInputBuffer(inputBufIndex);
}
int chunkSize = extractor.readSampleData(inputBuf, 0); int chunkSize = extractor.readSampleData(inputBuf, 0);
if (chunkSize < 0) { if (chunkSize < 0) {
decoder.queueInputBuffer(inputBufIndex, 0, 0, 0L, MediaCodec.BUFFER_FLAG_END_OF_STREAM); decoder.queueInputBuffer(inputBufIndex, 0, 0, 0L, MediaCodec.BUFFER_FLAG_END_OF_STREAM);
@ -439,9 +282,6 @@ public class VideoRecoder {
if (encoderStatus == MediaCodec.INFO_TRY_AGAIN_LATER) { if (encoderStatus == MediaCodec.INFO_TRY_AGAIN_LATER) {
encoderOutputAvailable = false; encoderOutputAvailable = false;
} else if (encoderStatus == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) { } else if (encoderStatus == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
if (Build.VERSION.SDK_INT < 21) {
encoderOutputBuffers = encoder.getOutputBuffers();
}
} else if (encoderStatus == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) { } else if (encoderStatus == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
MediaFormat newFormat = encoder.getOutputFormat(); MediaFormat newFormat = encoder.getOutputFormat();
if (videoTrackIndex == -5) { if (videoTrackIndex == -5) {
@ -451,11 +291,7 @@ public class VideoRecoder {
throw new RuntimeException("unexpected result from encoder.dequeueOutputBuffer: " + encoderStatus); throw new RuntimeException("unexpected result from encoder.dequeueOutputBuffer: " + encoderStatus);
} else { } else {
ByteBuffer encodedData; ByteBuffer encodedData;
if (Build.VERSION.SDK_INT < 21) { encodedData = encoder.getOutputBuffer(encoderStatus);
encodedData = encoderOutputBuffers[encoderStatus];
} else {
encodedData = encoder.getOutputBuffer(encoderStatus);
}
if (encodedData == null) { if (encodedData == null) {
throw new RuntimeException("encoderOutputBuffer " + encoderStatus + " was null"); throw new RuntimeException("encoderOutputBuffer " + encoderStatus + " was null");
} }
@ -513,11 +349,7 @@ public class VideoRecoder {
throw new RuntimeException("unexpected result from decoder.dequeueOutputBuffer: " + decoderStatus); throw new RuntimeException("unexpected result from decoder.dequeueOutputBuffer: " + decoderStatus);
} else { } else {
boolean doRender; boolean doRender;
if (Build.VERSION.SDK_INT >= 18) { doRender = info.size != 0;
doRender = info.size != 0;
} else {
doRender = info.size != 0 || info.presentationTimeUs != 0;
}
if (endTime > 0 && info.presentationTimeUs >= endTime) { if (endTime > 0 && info.presentationTimeUs >= endTime) {
inputDone = true; inputDone = true;
decoderDone = true; decoderDone = true;
@ -542,40 +374,15 @@ public class VideoRecoder {
Log.w(TAG, "error while waiting for recording output surface", e); Log.w(TAG, "error while waiting for recording output surface", e);
} }
if (!errorWait) { if (!errorWait) {
if (Build.VERSION.SDK_INT >= 18) { outputSurface.drawImage(false);
outputSurface.drawImage(false); inputSurface.setPresentationTime(info.presentationTimeUs * 1000);
inputSurface.setPresentationTime(info.presentationTimeUs * 1000); inputSurface.swapBuffers();
inputSurface.swapBuffers();
} else {
Log.w(TAG, "Cannot proceed with the current SDK version");
return false; // TODO: this should be caught much earlier
/*
int inputBufIndex = encoder.dequeueInputBuffer(TIMEOUT_USEC);
if (inputBufIndex >= 0) {
outputSurface.drawImage(true);
ByteBuffer rgbBuf = outputSurface.getFrame();
ByteBuffer yuvBuf = encoderInputBuffers[inputBufIndex];
yuvBuf.clear();
Utilities.convertVideoFrame(rgbBuf, yuvBuf, colorFormat, resultWidth, resultHeight, padding, swapUV);
encoder.queueInputBuffer(inputBufIndex, 0, bufferSize, info.presentationTimeUs, 0);
} else {
//Log.i("DeltaChat", "input buffer not available");
}
*/
}
} }
} }
if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) { if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
decoderOutputAvailable = false; decoderOutputAvailable = false;
//Log.i("DeltaChat", "decoder stream end"); //Log.i("DeltaChat", "decoder stream end");
if (Build.VERSION.SDK_INT >= 18) { encoder.signalEndOfInputStream();
encoder.signalEndOfInputStream();
} else {
int inputBufIndex = encoder.dequeueInputBuffer(TIMEOUT_USEC);
if (inputBufIndex >= 0) {
encoder.queueInputBuffer(inputBufIndex, 0, 1, info.presentationTimeUs, MediaCodec.BUFFER_FLAG_END_OF_STREAM);
}
}
} }
} }
} }
@ -662,45 +469,6 @@ public class VideoRecoder {
int estimatedBytes; int estimatedBytes;
} }
public static boolean canRecode()
{
boolean canRecode = true;
if (Build.VERSION.SDK_INT < 16 /*= Jelly Bean 4.1 (before that codecInfo.getName() was not there) */) {
Log.w(TAG, "Cannot recode: API < 16");
canRecode = false;
}
else if (Build.VERSION.SDK_INT < 18 /*= Jelly Bean 4.3*/) {
try {
MediaCodecInfo codecInfo = VideoRecoder.selectCodec(VideoRecoder.MIME_TYPE);
if (codecInfo == null) {
Log.w(TAG, "Cannot recode: cannot select codec");
canRecode = false;
} else {
String name = codecInfo.getName();
if (name.equals("OMX.google.h264.encoder") ||
name.equals("OMX.ST.VFM.H264Enc") ||
name.equals("OMX.Exynos.avc.enc") ||
name.equals("OMX.MARVELL.VIDEO.HW.CODA7542ENCODER") ||
name.equals("OMX.MARVELL.VIDEO.H264ENCODER") ||
name.equals("OMX.k3.video.encoder.avc") ||
name.equals("OMX.TI.DUCATI1.VIDEO.H264E")) {
Log.w(TAG, "Cannot recode: no supported codec found");
canRecode = false;
} else {
if (VideoRecoder.selectColorFormat(codecInfo, VideoRecoder.MIME_TYPE) == 0) {
Log.w(TAG, "Cannot recode: cannot select color format");
canRecode = false;
}
}
}
} catch (Exception e) {
Log.w(TAG, "Cannot recode: Determinating recoding capabilities failed unexpectedly", e);
canRecode = false;
}
}
return canRecode;
}
private static VideoEditedInfo getVideoEditInfoFromFile(String videoPath) { private static VideoEditedInfo getVideoEditInfoFromFile(String videoPath) {
// load information for the given video // load information for the given video
VideoEditedInfo vei = new VideoEditedInfo(); VideoEditedInfo vei = new VideoEditedInfo();
@ -811,11 +579,6 @@ public class VideoRecoder {
} }
msg.setDuration((int)vei.originalDurationMs); msg.setDuration((int)vei.originalDurationMs);
if (!canRecode()) {
alert(context, String.format("Recoding failed for %s: this system cannot recode videos", inPath));
return false;
}
// check if video bitrate is already reasonable // check if video bitrate is already reasonable
final int MAX_KBPS = 1500000; final int MAX_KBPS = 1500000;
final long MAX_BYTES = DcHelper.getInt(context, "sys.msgsize_max_recommended"); final long MAX_BYTES = DcHelper.getInt(context, "sys.msgsize_max_recommended");

View file

Before

Width:  |  Height:  |  Size: 1,002 B

After

Width:  |  Height:  |  Size: 1,002 B

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 750 B

View file

Before

Width:  |  Height:  |  Size: 532 B

After

Width:  |  Height:  |  Size: 532 B

Before After
Before After

View file

@ -1,9 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="@color/touch_highlight">
<item android:id="@android:id/mask">
<shape android:shape="oval">
<solid android:color="@color/black" />
</shape>
</item>
</ripple>

View file

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="@color/delta_primary">
<item android:id="@android:id/mask" android:drawable="@android:color/black" />
<item>
<selector>
<item android:drawable="@color/primary_alpha33" android:state_selected="true" />
</selector>
</item>
</ripple>

View file

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="@color/delta_primary">
<item android:id="@android:id/mask" android:drawable="@android:color/black" />
<item>
<selector>
<item android:drawable="@color/primary_alpha33" android:state_selected="true" />
</selector>
</item>
</ripple>

View file

@ -1,11 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="@color/delta_primary">
<item android:id="@android:id/mask" android:drawable="@android:color/black" />
<item>
<selector>
<item android:drawable="@color/primary_alpha33" android:state_selected="true" />
<item android:drawable="@color/pinned_bg" />
</selector>
</item>
</ripple>

View file

@ -1,11 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="@color/delta_primary">
<item android:id="@android:id/mask" android:drawable="@android:color/black" />
<item>
<selector>
<item android:drawable="@color/primary_alpha33" android:state_selected="true" />
<item android:drawable="@color/pinned_bg_dark" />
</selector>
</item>
</ripple>

View file

@ -1,7 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="@color/touch_highlight">
<item
android:id="@android:id/mask"
android:drawable="@android:color/white" />
</ripple>

View file

@ -1,12 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Like touch_highlight_background, but creates a stronger (i.e. better visible)
visual feedback when the button is pressed. -->
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="@color/delta_primary">
<item android:id="@android:id/mask" android:drawable="@android:color/white" />
<item>
<selector>
<item android:drawable="@color/touch_highlight_strong" android:state_pressed="true" />
</selector>
</item>
</ripple>

View file

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Before After
Before After

View file

@ -1,8 +1,9 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android"> <ripple xmlns:android="http://schemas.android.com/apk/res/android"
<item android:state_pressed="true"> android:color="@color/touch_highlight">
<item android:id="@android:id/mask">
<shape android:shape="oval"> <shape android:shape="oval">
<solid android:color="@color/touch_highlight" /> <solid android:color="@color/black" />
</shape> </shape>
</item> </item>
</selector> </ripple>

View file

@ -1,6 +1,10 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android"> <ripple xmlns:android="http://schemas.android.com/apk/res/android"
<item android:drawable="@color/primary_alpha33" android:state_selected="true" /> android:color="@color/delta_primary">
<item android:drawable="@color/primary_alpha33" android:state_pressed="true" /> <item android:id="@android:id/mask" android:drawable="@android:color/black" />
<item android:drawable="@color/primary_alpha_focus" android:state_focused="true" /> <item>
</selector> <selector>
<item android:drawable="@color/primary_alpha33" android:state_selected="true" />
</selector>
</item>
</ripple>

View file

@ -1,6 +1,10 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android"> <ripple xmlns:android="http://schemas.android.com/apk/res/android"
<item android:drawable="@color/primary_alpha33" android:state_selected="true" /> android:color="@color/delta_primary">
<item android:drawable="@color/primary_alpha33" android:state_pressed="true" /> <item android:id="@android:id/mask" android:drawable="@android:color/black" />
<item android:drawable="@color/primary_alpha_focus" android:state_focused="true" /> <item>
</selector> <selector>
<item android:drawable="@color/primary_alpha33" android:state_selected="true" />
</selector>
</item>
</ripple>

View file

@ -2,7 +2,7 @@
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android" <animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:drawable="@drawable/pause_icon" android:drawable="@drawable/pause_icon"
tools:targetApi="lollipop"> >
<target <target
android:name="@string/play_icon_group_parts" android:name="@string/play_icon_group_parts"

View file

@ -1,7 +1,11 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android"> <ripple xmlns:android="http://schemas.android.com/apk/res/android"
<item android:drawable="@color/primary_alpha33" android:state_selected="true" /> android:color="@color/delta_primary">
<item android:drawable="@color/primary_alpha33" android:state_pressed="true" /> <item android:id="@android:id/mask" android:drawable="@android:color/black" />
<item android:drawable="@color/primary_alpha_focus" android:state_focused="true" /> <item>
<item android:drawable="@color/pinned_bg" /> <selector>
</selector> <item android:drawable="@color/primary_alpha33" android:state_selected="true" />
<item android:drawable="@color/pinned_bg" />
</selector>
</item>
</ripple>

View file

@ -1,7 +1,11 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android"> <ripple xmlns:android="http://schemas.android.com/apk/res/android"
<item android:drawable="@color/primary_alpha33" android:state_selected="true" /> android:color="@color/delta_primary">
<item android:drawable="@color/primary_alpha33" android:state_pressed="true" /> <item android:id="@android:id/mask" android:drawable="@android:color/black" />
<item android:drawable="@color/primary_alpha_focus" android:state_focused="true" /> <item>
<item android:drawable="@color/pinned_bg_dark" /> <selector>
</selector> <item android:drawable="@color/primary_alpha33" android:state_selected="true" />
<item android:drawable="@color/pinned_bg_dark" />
</selector>
</item>
</ripple>

View file

@ -2,7 +2,7 @@
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android" <animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:drawable="@drawable/play_icon" android:drawable="@drawable/play_icon"
tools:targetApi="lollipop"> >
<target <target
android:name="@string/play_icon_group_parts" android:name="@string/play_icon_group_parts"

View file

@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android"> <ripple xmlns:android="http://schemas.android.com/apk/res/android"
<item android:state_pressed="true" android:drawable="@color/touch_highlight" /> android:color="@color/touch_highlight">
<item android:state_focused="true" android:drawable="@color/delta_primary" /> <item
<item android:drawable="@android:color/transparent" /> android:id="@android:id/mask"
</selector> android:drawable="@android:color/white" />
</ripple>

View file

@ -1,6 +1,12 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android"> <!-- Like touch_highlight_background, but creates a stronger (i.e. better visible)
<item android:state_pressed="true" android:drawable="@color/touch_highlight_strong" /> visual feedback when the button is pressed. -->
<item android:state_focused="true" android:drawable="@color/delta_primary" /> <ripple xmlns:android="http://schemas.android.com/apk/res/android"
<item android:drawable="@android:color/transparent" /> android:color="@color/delta_primary">
</selector> <item android:id="@android:id/mask" android:drawable="@android:color/white" />
<item>
<selector>
<item android:drawable="@color/touch_highlight_strong" android:state_pressed="true" />
</selector>
</item>
</ripple>

View file

@ -1,4 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="touch_highlight">#22000000</color>
</resources>

View file

@ -1,7 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="TextSecure.ScribbleTheme" parent="TextSecure.DarkNoActionBar">
<item name="android:windowNoTitle">true</item>
<item name="android:windowFullscreen">true</item>
</style>
</resources>

View file

@ -36,7 +36,7 @@
<color name="conversation_compose_divider">#32000000</color> <color name="conversation_compose_divider">#32000000</color>
<color name="action_mode_status_bar">@color/gray50</color> <color name="action_mode_status_bar">@color/gray50</color>
<color name="touch_highlight">#400099cc</color> <color name="touch_highlight">#22000000</color>
<color name="touch_highlight_strong">#5C4CB8DB</color> <color name="touch_highlight_strong">#5C4CB8DB</color>
<color name="sticker_selected_color">#99ffffff</color> <color name="sticker_selected_color">#99ffffff</color>

View file

@ -256,6 +256,8 @@
</style> </style>
<style name="TextSecure.ScribbleTheme" parent="TextSecure.DarkNoActionBar"> <style name="TextSecure.ScribbleTheme" parent="TextSecure.DarkNoActionBar">
<item name="android:windowNoTitle">true</item>
<item name="android:windowFullscreen">true</item>
</style> </style>
</resources> </resources>