Updater: The great cleanup
* Make final where possible * Remove unused casts, imports, methods, enums and constructors * Add null checks Change-Id: Idd1a16426dd1928e2ed9922f5a35ba32ce4f808b
This commit is contained in:
@@ -1,13 +1,14 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<LinearLayout
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
android:id="@+id/main_container"
|
android:id="@+id/main_container"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:fitsSystemWindows="true"
|
android:fitsSystemWindows="true"
|
||||||
android:padding="16dp"
|
android:padding="16dp"
|
||||||
android:weightSum="2">
|
android:weightSum="2"
|
||||||
|
android:baselineAligned="false">
|
||||||
|
|
||||||
<RelativeLayout
|
<RelativeLayout
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
@@ -29,57 +30,57 @@
|
|||||||
android:fontFamily="sans-serif-light"
|
android:fontFamily="sans-serif-light"
|
||||||
android:paddingBottom="16dp"
|
android:paddingBottom="16dp"
|
||||||
android:textColor="?android:attr/textColorPrimary"
|
android:textColor="?android:attr/textColorPrimary"
|
||||||
android:textSize="56sp" />
|
android:textSize="56sp"
|
||||||
|
tools:text="LineageOS\n18.1" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/header_build_version"
|
android:id="@+id/header_build_version"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_below="@id/header_title"
|
|
||||||
android:textColor="?android:attr/textColorPrimary"
|
android:textColor="?android:attr/textColorPrimary"
|
||||||
android:textSize="14sp" />
|
android:textSize="14sp"
|
||||||
|
tools:text="Android 11"/>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/header_build_date"
|
android:id="@+id/header_build_date"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_below="@id/header_build_version"
|
|
||||||
android:textColor="?android:attr/textColorPrimary"
|
android:textColor="?android:attr/textColorPrimary"
|
||||||
android:textSize="14sp" />
|
android:textSize="14sp"
|
||||||
|
tools:text="2022-01-01"/>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/header_last_check"
|
android:id="@+id/header_last_check"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_below="@id/header_build_date"
|
|
||||||
android:textColor="?android:attr/textColorPrimary"
|
android:textColor="?android:attr/textColorPrimary"
|
||||||
android:textSize="14sp" />
|
android:textSize="14sp"
|
||||||
|
tools:text="Last checked: 2022-01-01"/>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_below="@id/header_last_check"
|
|
||||||
android:layout_alignParentBottom="true"
|
android:layout_alignParentBottom="true"
|
||||||
android:weightSum="2"
|
android:weightSum="2"
|
||||||
android:orientation="horizontal">
|
android:orientation="horizontal">
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/refresh"
|
android:id="@+id/refresh"
|
||||||
android:drawableLeft="@drawable/ic_menu_refresh"
|
android:drawableStart="@drawable/ic_menu_refresh"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
android:text="refresh"
|
android:text="@string/menu_refresh"
|
||||||
style="@style/Widget.AppCompat.Button.Borderless.Colored"/>
|
style="@style/Widget.AppCompat.Button.Borderless.Colored"/>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/preferences"
|
android:id="@+id/preferences"
|
||||||
android:drawableLeft="@drawable/ic_menu_preferences"
|
android:drawableStart="@drawable/ic_menu_preferences"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
android:text="preferences"
|
android:text="@string/menu_preferences"
|
||||||
style="@style/Widget.AppCompat.Button.Borderless.Colored"/>
|
style="@style/Widget.AppCompat.Button.Borderless.Colored"/>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
@@ -16,7 +16,8 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
android:weightSum="1">
|
android:weightSum="1"
|
||||||
|
android:baselineAligned="false">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
@@ -90,7 +91,8 @@
|
|||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="end"
|
android:layout_gravity="end"
|
||||||
android:padding="8dp" />
|
android:padding="8dp"
|
||||||
|
android:contentDescription="@null" />
|
||||||
<Button
|
<Button
|
||||||
android:id="@id/update_action"
|
android:id="@id/update_action"
|
||||||
style="@style/Widget.AppCompat.Button.Borderless.Colored"
|
style="@style/Widget.AppCompat.Button.Borderless.Colored"
|
||||||
|
@@ -29,7 +29,7 @@
|
|||||||
android:entries="@array/menu_auto_updates_check_interval_entries" />
|
android:entries="@array/menu_auto_updates_check_interval_entries" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<Switch
|
<androidx.appcompat.widget.SwitchCompat
|
||||||
android:id="@+id/preferences_auto_delete_updates"
|
android:id="@+id/preferences_auto_delete_updates"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
@@ -37,7 +37,7 @@
|
|||||||
android:text="@string/menu_auto_delete_updates"
|
android:text="@string/menu_auto_delete_updates"
|
||||||
android:textSize="16sp" />
|
android:textSize="16sp" />
|
||||||
|
|
||||||
<Switch
|
<androidx.appcompat.widget.SwitchCompat
|
||||||
android:id="@+id/preferences_mobile_data_warning"
|
android:id="@+id/preferences_mobile_data_warning"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
@@ -45,7 +45,7 @@
|
|||||||
android:text="@string/menu_mobile_data_warning"
|
android:text="@string/menu_mobile_data_warning"
|
||||||
android:textSize="16sp" />
|
android:textSize="16sp" />
|
||||||
|
|
||||||
<Switch
|
<androidx.appcompat.widget.SwitchCompat
|
||||||
android:id="@+id/preferences_ab_perf_mode"
|
android:id="@+id/preferences_ab_perf_mode"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
@@ -53,7 +53,7 @@
|
|||||||
android:text="@string/menu_ab_perf_mode"
|
android:text="@string/menu_ab_perf_mode"
|
||||||
android:textSize="16sp" />
|
android:textSize="16sp" />
|
||||||
|
|
||||||
<Switch
|
<androidx.appcompat.widget.SwitchCompat
|
||||||
android:id="@+id/preferences_update_recovery"
|
android:id="@+id/preferences_update_recovery"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
@@ -15,7 +15,8 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
android:weightSum="1">
|
android:weightSum="1"
|
||||||
|
android:baselineAligned="false">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
@@ -89,7 +90,8 @@
|
|||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="end"
|
android:layout_gravity="end"
|
||||||
android:padding="8dp" />
|
android:padding="8dp"
|
||||||
|
android:contentDescription="@null" />
|
||||||
<Button
|
<Button
|
||||||
android:id="@id/update_action"
|
android:id="@id/update_action"
|
||||||
style="@style/Widget.AppCompat.Button.Borderless.Colored"
|
style="@style/Widget.AppCompat.Button.Borderless.Colored"
|
||||||
|
@@ -1,6 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
|
||||||
<item
|
<item
|
||||||
android:id="@+id/menu_export_update"
|
android:id="@+id/menu_export_update"
|
||||||
android:title="@string/menu_export_update" />
|
android:title="@string/menu_export_update" />
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2017 The LineageOS Project
|
* Copyright (C) 2017-2022 The LineageOS Project
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -94,11 +94,11 @@ public class ExportUpdateService extends Service {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private class ExportRunnable implements Runnable {
|
private class ExportRunnable implements Runnable {
|
||||||
private File mSource;
|
private final File mSource;
|
||||||
private File mDestination;
|
private final File mDestination;
|
||||||
private FileUtils.ProgressCallBack mProgressCallBack;
|
private final FileUtils.ProgressCallBack mProgressCallBack;
|
||||||
private Runnable mRunnableComplete;
|
private final Runnable mRunnableComplete;
|
||||||
private Runnable mRunnableFailed;
|
private final Runnable mRunnableFailed;
|
||||||
|
|
||||||
private ExportRunnable(File source, File destination,
|
private ExportRunnable(File source, File destination,
|
||||||
FileUtils.ProgressCallBack progressCallBack,
|
FileUtils.ProgressCallBack progressCallBack,
|
||||||
@@ -131,13 +131,13 @@ public class ExportUpdateService extends Service {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void cleanUp() {
|
private void cleanUp() {
|
||||||
|
//noinspection ResultOfMethodCallIgnored
|
||||||
mDestination.delete();
|
mDestination.delete();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void startExporting(File source, File destination) {
|
private void startExporting(File source, File destination) {
|
||||||
NotificationManager notificationManager =
|
NotificationManager notificationManager = getSystemService(NotificationManager.class);
|
||||||
(NotificationManager) getSystemService(NOTIFICATION_SERVICE);
|
|
||||||
NotificationChannel notificationChannel = new NotificationChannel(
|
NotificationChannel notificationChannel = new NotificationChannel(
|
||||||
EXPORT_NOTIFICATION_CHANNEL,
|
EXPORT_NOTIFICATION_CHANNEL,
|
||||||
getString(R.string.export_channel_title),
|
getString(R.string.export_channel_title),
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2017 The LineageOS Project
|
* Copyright (C) 2017-2022 The LineageOS Project
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -79,8 +79,7 @@ public class UpdaterReceiver extends BroadcastReceiver {
|
|||||||
.setStyle(new NotificationCompat.BigTextStyle().bigText(buildInfo))
|
.setStyle(new NotificationCompat.BigTextStyle().bigText(buildInfo))
|
||||||
.setContentText(buildInfo);
|
.setContentText(buildInfo);
|
||||||
|
|
||||||
NotificationManager nm = (NotificationManager) context.getSystemService(
|
NotificationManager nm = context.getSystemService(NotificationManager.class);
|
||||||
Context.NOTIFICATION_SERVICE);
|
|
||||||
nm.createNotificationChannel(notificationChannel);
|
nm.createNotificationChannel(notificationChannel);
|
||||||
nm.notify(0, builder.build());
|
nm.notify(0, builder.build());
|
||||||
}
|
}
|
||||||
@@ -88,7 +87,7 @@ public class UpdaterReceiver extends BroadcastReceiver {
|
|||||||
@Override
|
@Override
|
||||||
public void onReceive(Context context, Intent intent) {
|
public void onReceive(Context context, Intent intent) {
|
||||||
if (ACTION_INSTALL_REBOOT.equals(intent.getAction())) {
|
if (ACTION_INSTALL_REBOOT.equals(intent.getAction())) {
|
||||||
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
|
PowerManager pm = context.getSystemService(PowerManager.class);
|
||||||
pm.reboot(null);
|
pm.reboot(null);
|
||||||
} else if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) {
|
} else if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) {
|
||||||
SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(context);
|
SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(context);
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2017-2020 The LineageOS Project
|
* Copyright (C) 2017-2022 The LineageOS Project
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -15,6 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.lineageos.updater;
|
package org.lineageos.updater;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
import android.app.UiModeManager;
|
import android.app.UiModeManager;
|
||||||
import android.content.BroadcastReceiver;
|
import android.content.BroadcastReceiver;
|
||||||
import android.content.ComponentName;
|
import android.content.ComponentName;
|
||||||
@@ -39,14 +40,13 @@ import android.view.View;
|
|||||||
import android.view.animation.Animation;
|
import android.view.animation.Animation;
|
||||||
import android.view.animation.LinearInterpolator;
|
import android.view.animation.LinearInterpolator;
|
||||||
import android.view.animation.RotateAnimation;
|
import android.view.animation.RotateAnimation;
|
||||||
import android.widget.Button;
|
|
||||||
import android.widget.Spinner;
|
import android.widget.Spinner;
|
||||||
import android.widget.Switch;
|
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import androidx.appcompat.app.ActionBar;
|
||||||
import androidx.appcompat.app.AlertDialog;
|
import androidx.appcompat.app.AlertDialog;
|
||||||
import androidx.appcompat.app.AppCompatDelegate;
|
import androidx.appcompat.widget.SwitchCompat;
|
||||||
import androidx.appcompat.widget.Toolbar;
|
import androidx.appcompat.widget.Toolbar;
|
||||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
||||||
import androidx.preference.PreferenceManager;
|
import androidx.preference.PreferenceManager;
|
||||||
@@ -92,10 +92,10 @@ public class UpdatesActivity extends UpdatesListActivity {
|
|||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
setContentView(R.layout.activity_updates);
|
setContentView(R.layout.activity_updates);
|
||||||
|
|
||||||
UiModeManager uiModeManager = (UiModeManager) getSystemService(UI_MODE_SERVICE);
|
UiModeManager uiModeManager = getSystemService(UiModeManager.class);
|
||||||
mIsTV = uiModeManager.getCurrentModeType() == Configuration.UI_MODE_TYPE_TELEVISION;
|
mIsTV = uiModeManager.getCurrentModeType() == Configuration.UI_MODE_TYPE_TELEVISION;
|
||||||
|
|
||||||
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
|
RecyclerView recyclerView = findViewById(R.id.recycler_view);
|
||||||
mAdapter = new UpdatesListAdapter(this);
|
mAdapter = new UpdatesListAdapter(this);
|
||||||
recyclerView.setAdapter(mAdapter);
|
recyclerView.setAdapter(mAdapter);
|
||||||
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(this);
|
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(this);
|
||||||
@@ -111,7 +111,7 @@ public class UpdatesActivity extends UpdatesListActivity {
|
|||||||
if (UpdaterController.ACTION_UPDATE_STATUS.equals(intent.getAction())) {
|
if (UpdaterController.ACTION_UPDATE_STATUS.equals(intent.getAction())) {
|
||||||
String downloadId = intent.getStringExtra(UpdaterController.EXTRA_DOWNLOAD_ID);
|
String downloadId = intent.getStringExtra(UpdaterController.EXTRA_DOWNLOAD_ID);
|
||||||
handleDownloadStatusChange(downloadId);
|
handleDownloadStatusChange(downloadId);
|
||||||
mAdapter.notifyDataSetChanged();
|
mAdapter.notifyItemChanged(downloadId);
|
||||||
} else if (UpdaterController.ACTION_DOWNLOAD_PROGRESS.equals(intent.getAction()) ||
|
} else if (UpdaterController.ACTION_DOWNLOAD_PROGRESS.equals(intent.getAction()) ||
|
||||||
UpdaterController.ACTION_INSTALL_PROGRESS.equals(intent.getAction())) {
|
UpdaterController.ACTION_INSTALL_PROGRESS.equals(intent.getAction())) {
|
||||||
String downloadId = intent.getStringExtra(UpdaterController.EXTRA_DOWNLOAD_ID);
|
String downloadId = intent.getStringExtra(UpdaterController.EXTRA_DOWNLOAD_ID);
|
||||||
@@ -124,31 +124,33 @@ public class UpdatesActivity extends UpdatesListActivity {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (!mIsTV) {
|
if (!mIsTV) {
|
||||||
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
|
Toolbar toolbar = findViewById(R.id.toolbar);
|
||||||
setSupportActionBar(toolbar);
|
setSupportActionBar(toolbar);
|
||||||
getSupportActionBar().setDisplayShowTitleEnabled(false);
|
ActionBar actionBar = getSupportActionBar();
|
||||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
if (actionBar != null) {
|
||||||
|
actionBar.setDisplayShowTitleEnabled(false);
|
||||||
|
actionBar.setDisplayHomeAsUpEnabled(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TextView headerTitle = (TextView) findViewById(R.id.header_title);
|
TextView headerTitle = findViewById(R.id.header_title);
|
||||||
headerTitle.setText(getString(R.string.header_title_text,
|
headerTitle.setText(getString(R.string.header_title_text,
|
||||||
BuildInfoUtils.getBuildVersion()));
|
BuildInfoUtils.getBuildVersion()));
|
||||||
|
|
||||||
updateLastCheckedString();
|
updateLastCheckedString();
|
||||||
|
|
||||||
TextView headerBuildVersion = (TextView) findViewById(R.id.header_build_version);
|
TextView headerBuildVersion = findViewById(R.id.header_build_version);
|
||||||
headerBuildVersion.setText(
|
headerBuildVersion.setText(
|
||||||
getString(R.string.header_android_version, Build.VERSION.RELEASE));
|
getString(R.string.header_android_version, Build.VERSION.RELEASE));
|
||||||
|
|
||||||
TextView headerBuildDate = (TextView) findViewById(R.id.header_build_date);
|
TextView headerBuildDate = findViewById(R.id.header_build_date);
|
||||||
headerBuildDate.setText(StringGenerator.getDateLocalizedUTC(this,
|
headerBuildDate.setText(StringGenerator.getDateLocalizedUTC(this,
|
||||||
DateFormat.LONG, BuildInfoUtils.getBuildDateTimestamp()));
|
DateFormat.LONG, BuildInfoUtils.getBuildDateTimestamp()));
|
||||||
|
|
||||||
if (!mIsTV) {
|
if (!mIsTV) {
|
||||||
// Switch between header title and appbar title minimizing overlaps
|
// Switch between header title and appbar title minimizing overlaps
|
||||||
final CollapsingToolbarLayout collapsingToolbar =
|
final CollapsingToolbarLayout collapsingToolbar = findViewById(R.id.collapsing_toolbar);
|
||||||
(CollapsingToolbarLayout) findViewById(R.id.collapsing_toolbar);
|
final AppBarLayout appBar = findViewById(R.id.app_bar);
|
||||||
final AppBarLayout appBar = (AppBarLayout) findViewById(R.id.app_bar);
|
|
||||||
appBar.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() {
|
appBar.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() {
|
||||||
boolean mIsShown = false;
|
boolean mIsShown = false;
|
||||||
|
|
||||||
@@ -175,18 +177,8 @@ public class UpdatesActivity extends UpdatesListActivity {
|
|||||||
appBar.setExpanded(false);
|
appBar.setExpanded(false);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
findViewById(R.id.refresh).setOnClickListener(new View.OnClickListener() {
|
findViewById(R.id.refresh).setOnClickListener(v -> downloadUpdatesList(true));
|
||||||
@Override
|
findViewById(R.id.preferences).setOnClickListener(v -> showPreferencesDialog());
|
||||||
public void onClick(View v) {
|
|
||||||
downloadUpdatesList(true);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
findViewById(R.id.preferences).setOnClickListener(new View.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(View v) {
|
|
||||||
showPreferencesDialog();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -222,22 +214,19 @@ public class UpdatesActivity extends UpdatesListActivity {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onOptionsItemSelected(MenuItem item) {
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
switch (item.getItemId()) {
|
int itemId = item.getItemId();
|
||||||
case R.id.menu_refresh: {
|
if (itemId == R.id.menu_refresh) {
|
||||||
downloadUpdatesList(true);
|
downloadUpdatesList(true);
|
||||||
return true;
|
return true;
|
||||||
}
|
} else if (itemId == R.id.menu_preferences) {
|
||||||
case R.id.menu_preferences: {
|
|
||||||
showPreferencesDialog();
|
showPreferencesDialog();
|
||||||
return true;
|
return true;
|
||||||
}
|
} else if (itemId == R.id.menu_show_changelog) {
|
||||||
case R.id.menu_show_changelog: {
|
|
||||||
Intent openUrl = new Intent(Intent.ACTION_VIEW,
|
Intent openUrl = new Intent(Intent.ACTION_VIEW,
|
||||||
Uri.parse(Utils.getChangelogURL(this)));
|
Uri.parse(Utils.getChangelogURL(this)));
|
||||||
startActivity(openUrl);
|
startActivity(openUrl);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return super.onOptionsItemSelected(item);
|
return super.onOptionsItemSelected(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -247,7 +236,7 @@ public class UpdatesActivity extends UpdatesListActivity {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ServiceConnection mConnection = new ServiceConnection() {
|
private final ServiceConnection mConnection = new ServiceConnection() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onServiceConnected(ComponentName className,
|
public void onServiceConnected(ComponentName className,
|
||||||
@@ -330,6 +319,7 @@ public class UpdatesActivity extends UpdatesListActivity {
|
|||||||
}
|
}
|
||||||
// In case we set a one-shot check because of a previous failure
|
// In case we set a one-shot check because of a previous failure
|
||||||
UpdatesCheckReceiver.cancelUpdatesCheck(this);
|
UpdatesCheckReceiver.cancelUpdatesCheck(this);
|
||||||
|
//noinspection ResultOfMethodCallIgnored
|
||||||
jsonNew.renameTo(json);
|
jsonNew.renameTo(json);
|
||||||
} catch (IOException | JSONException e) {
|
} catch (IOException | JSONException e) {
|
||||||
Log.e(TAG, "Could not read json", e);
|
Log.e(TAG, "Could not read json", e);
|
||||||
@@ -356,12 +346,11 @@ public class UpdatesActivity extends UpdatesListActivity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onResponse(int statusCode, String url,
|
public void onResponse(DownloadClient.Headers headers) {
|
||||||
DownloadClient.Headers headers) {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSuccess(File destination) {
|
public void onSuccess() {
|
||||||
runOnUiThread(() -> {
|
runOnUiThread(() -> {
|
||||||
Log.d(TAG, "List downloaded");
|
Log.d(TAG, "List downloaded");
|
||||||
processNewJson(jsonFile, jsonFileTmp, manualRefresh);
|
processNewJson(jsonFile, jsonFileTmp, manualRefresh);
|
||||||
@@ -394,7 +383,7 @@ public class UpdatesActivity extends UpdatesListActivity {
|
|||||||
String lastCheckString = getString(R.string.header_last_updates_check,
|
String lastCheckString = getString(R.string.header_last_updates_check,
|
||||||
StringGenerator.getDateLocalized(this, DateFormat.LONG, lastCheck),
|
StringGenerator.getDateLocalized(this, DateFormat.LONG, lastCheck),
|
||||||
StringGenerator.getTimeLocalized(this, lastCheck));
|
StringGenerator.getTimeLocalized(this, lastCheck));
|
||||||
TextView headerLastCheck = (TextView) findViewById(R.id.header_last_check);
|
TextView headerLastCheck = findViewById(R.id.header_last_check);
|
||||||
headerLastCheck.setText(lastCheckString);
|
headerLastCheck.setText(lastCheckString);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -451,14 +440,14 @@ public class UpdatesActivity extends UpdatesListActivity {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressLint("ClickableViewAccessibility")
|
||||||
private void showPreferencesDialog() {
|
private void showPreferencesDialog() {
|
||||||
View view = LayoutInflater.from(this).inflate(R.layout.preferences_dialog, null);
|
View view = LayoutInflater.from(this).inflate(R.layout.preferences_dialog, null);
|
||||||
Spinner autoCheckInterval =
|
Spinner autoCheckInterval = view.findViewById(R.id.preferences_auto_updates_check_interval);
|
||||||
view.findViewById(R.id.preferences_auto_updates_check_interval);
|
SwitchCompat autoDelete = view.findViewById(R.id.preferences_auto_delete_updates);
|
||||||
Switch autoDelete = view.findViewById(R.id.preferences_auto_delete_updates);
|
SwitchCompat dataWarning = view.findViewById(R.id.preferences_mobile_data_warning);
|
||||||
Switch dataWarning = view.findViewById(R.id.preferences_mobile_data_warning);
|
SwitchCompat abPerfMode = view.findViewById(R.id.preferences_ab_perf_mode);
|
||||||
Switch abPerfMode = view.findViewById(R.id.preferences_ab_perf_mode);
|
SwitchCompat updateRecovery = view.findViewById(R.id.preferences_update_recovery);
|
||||||
Switch updateRecovery = view.findViewById(R.id.preferences_update_recovery);
|
|
||||||
|
|
||||||
if (!Utils.isABDevice()) {
|
if (!Utils.isABDevice()) {
|
||||||
abPerfMode.setVisibility(View.GONE);
|
abPerfMode.setVisibility(View.GONE);
|
||||||
@@ -471,7 +460,7 @@ public class UpdatesActivity extends UpdatesListActivity {
|
|||||||
abPerfMode.setChecked(prefs.getBoolean(Constants.PREF_AB_PERF_MODE, false));
|
abPerfMode.setChecked(prefs.getBoolean(Constants.PREF_AB_PERF_MODE, false));
|
||||||
|
|
||||||
if (getResources().getBoolean(R.bool.config_hideRecoveryUpdate)) {
|
if (getResources().getBoolean(R.bool.config_hideRecoveryUpdate)) {
|
||||||
// Hide the update feature if explicitely requested.
|
// Hide the update feature if explicitly requested.
|
||||||
// Might be the case of A-only devices using prebuilt vendor images.
|
// Might be the case of A-only devices using prebuilt vendor images.
|
||||||
updateRecovery.setVisibility(View.GONE);
|
updateRecovery.setVisibility(View.GONE);
|
||||||
} else if (Utils.isRecoveryUpdateExecPresent()) {
|
} else if (Utils.isRecoveryUpdateExecPresent()) {
|
||||||
@@ -505,12 +494,9 @@ public class UpdatesActivity extends UpdatesListActivity {
|
|||||||
prefs.edit()
|
prefs.edit()
|
||||||
.putInt(Constants.PREF_AUTO_UPDATES_CHECK_INTERVAL,
|
.putInt(Constants.PREF_AUTO_UPDATES_CHECK_INTERVAL,
|
||||||
autoCheckInterval.getSelectedItemPosition())
|
autoCheckInterval.getSelectedItemPosition())
|
||||||
.putBoolean(Constants.PREF_AUTO_DELETE_UPDATES,
|
.putBoolean(Constants.PREF_AUTO_DELETE_UPDATES, autoDelete.isChecked())
|
||||||
autoDelete.isChecked())
|
.putBoolean(Constants.PREF_MOBILE_DATA_WARNING, dataWarning.isChecked())
|
||||||
.putBoolean(Constants.PREF_MOBILE_DATA_WARNING,
|
.putBoolean(Constants.PREF_AB_PERF_MODE, abPerfMode.isChecked())
|
||||||
dataWarning.isChecked())
|
|
||||||
.putBoolean(Constants.PREF_AB_PERF_MODE,
|
|
||||||
abPerfMode.isChecked())
|
|
||||||
.apply();
|
.apply();
|
||||||
|
|
||||||
if (Utils.isUpdateCheckEnabled(this)) {
|
if (Utils.isUpdateCheckEnabled(this)) {
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2017 The LineageOS Project
|
* Copyright (C) 2017-2022 The LineageOS Project
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -84,17 +84,17 @@ public class UpdatesCheckReceiver extends BroadcastReceiver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onResponse(int statusCode, String url,
|
public void onResponse(DownloadClient.Headers headers) {
|
||||||
DownloadClient.Headers headers) {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSuccess(File destination) {
|
public void onSuccess() {
|
||||||
try {
|
try {
|
||||||
if (json.exists() && Utils.checkForNewUpdates(json, jsonNew)) {
|
if (json.exists() && Utils.checkForNewUpdates(json, jsonNew)) {
|
||||||
showNotification(context);
|
showNotification(context);
|
||||||
updateRepeatingUpdatesCheck(context);
|
updateRepeatingUpdatesCheck(context);
|
||||||
}
|
}
|
||||||
|
//noinspection ResultOfMethodCallIgnored
|
||||||
jsonNew.renameTo(json);
|
jsonNew.renameTo(json);
|
||||||
long currentMillis = System.currentTimeMillis();
|
long currentMillis = System.currentTimeMillis();
|
||||||
preferences.edit()
|
preferences.edit()
|
||||||
@@ -123,8 +123,8 @@ public class UpdatesCheckReceiver extends BroadcastReceiver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static void showNotification(Context context) {
|
private static void showNotification(Context context) {
|
||||||
NotificationManager notificationManager =
|
NotificationManager notificationManager = context.getSystemService(
|
||||||
(NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
|
NotificationManager.class);
|
||||||
NotificationChannel notificationChannel = new NotificationChannel(
|
NotificationChannel notificationChannel = new NotificationChannel(
|
||||||
NEW_UPDATES_NOTIFICATION_CHANNEL,
|
NEW_UPDATES_NOTIFICATION_CHANNEL,
|
||||||
context.getString(R.string.new_updates_channel_title),
|
context.getString(R.string.new_updates_channel_title),
|
||||||
@@ -159,7 +159,7 @@ public class UpdatesCheckReceiver extends BroadcastReceiver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
PendingIntent updateCheckIntent = getRepeatingUpdatesCheckIntent(context);
|
PendingIntent updateCheckIntent = getRepeatingUpdatesCheckIntent(context);
|
||||||
AlarmManager alarmMgr = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
|
AlarmManager alarmMgr = context.getSystemService(AlarmManager.class);
|
||||||
alarmMgr.setRepeating(AlarmManager.RTC, System.currentTimeMillis() +
|
alarmMgr.setRepeating(AlarmManager.RTC, System.currentTimeMillis() +
|
||||||
Utils.getUpdateCheckInterval(context), Utils.getUpdateCheckInterval(context),
|
Utils.getUpdateCheckInterval(context), Utils.getUpdateCheckInterval(context),
|
||||||
updateCheckIntent);
|
updateCheckIntent);
|
||||||
@@ -170,7 +170,7 @@ public class UpdatesCheckReceiver extends BroadcastReceiver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void cancelRepeatingUpdatesCheck(Context context) {
|
public static void cancelRepeatingUpdatesCheck(Context context) {
|
||||||
AlarmManager alarmMgr = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
|
AlarmManager alarmMgr = context.getSystemService(AlarmManager.class);
|
||||||
alarmMgr.cancel(getRepeatingUpdatesCheckIntent(context));
|
alarmMgr.cancel(getRepeatingUpdatesCheckIntent(context));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -183,7 +183,7 @@ public class UpdatesCheckReceiver extends BroadcastReceiver {
|
|||||||
public static void scheduleUpdatesCheck(Context context) {
|
public static void scheduleUpdatesCheck(Context context) {
|
||||||
long millisToNextCheck = AlarmManager.INTERVAL_HOUR * 2;
|
long millisToNextCheck = AlarmManager.INTERVAL_HOUR * 2;
|
||||||
PendingIntent updateCheckIntent = getUpdatesCheckIntent(context);
|
PendingIntent updateCheckIntent = getUpdatesCheckIntent(context);
|
||||||
AlarmManager alarmMgr = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
|
AlarmManager alarmMgr = context.getSystemService(AlarmManager.class);
|
||||||
alarmMgr.set(AlarmManager.ELAPSED_REALTIME,
|
alarmMgr.set(AlarmManager.ELAPSED_REALTIME,
|
||||||
SystemClock.elapsedRealtime() + millisToNextCheck,
|
SystemClock.elapsedRealtime() + millisToNextCheck,
|
||||||
updateCheckIntent);
|
updateCheckIntent);
|
||||||
@@ -193,7 +193,7 @@ public class UpdatesCheckReceiver extends BroadcastReceiver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void cancelUpdatesCheck(Context context) {
|
public static void cancelUpdatesCheck(Context context) {
|
||||||
AlarmManager alarmMgr = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
|
AlarmManager alarmMgr = context.getSystemService(AlarmManager.class);
|
||||||
alarmMgr.cancel(getUpdatesCheckIntent(context));
|
alarmMgr.cancel(getUpdatesCheckIntent(context));
|
||||||
Log.d(TAG, "Cancelling pending one-shot check");
|
Log.d(TAG, "Cancelling pending one-shot check");
|
||||||
}
|
}
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2017 The LineageOS Project
|
* Copyright (C) 2017-2022 The LineageOS Project
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -75,18 +75,11 @@ public class UpdatesDbHelper extends SQLiteOpenHelper {
|
|||||||
onUpgrade(db, oldVersion, newVersion);
|
onUpgrade(db, oldVersion, newVersion);
|
||||||
}
|
}
|
||||||
|
|
||||||
public long addUpdate(Update update) {
|
public void addUpdateWithOnConflict(Update update, int conflictAlgorithm) {
|
||||||
SQLiteDatabase db = getWritableDatabase();
|
SQLiteDatabase db = getWritableDatabase();
|
||||||
ContentValues values = new ContentValues();
|
ContentValues values = new ContentValues();
|
||||||
fillContentValues(update, values);
|
fillContentValues(update, values);
|
||||||
return db.insert(UpdateEntry.TABLE_NAME, null, values);
|
db.insertWithOnConflict(UpdateEntry.TABLE_NAME, null, values, conflictAlgorithm);
|
||||||
}
|
|
||||||
|
|
||||||
public long addUpdateWithOnConflict(Update update, int conflictAlgorithm) {
|
|
||||||
SQLiteDatabase db = getWritableDatabase();
|
|
||||||
ContentValues values = new ContentValues();
|
|
||||||
fillContentValues(update, values);
|
|
||||||
return db.insertWithOnConflict(UpdateEntry.TABLE_NAME, null, values, conflictAlgorithm);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void fillContentValues(Update update, ContentValues values) {
|
private static void fillContentValues(Update update, ContentValues values) {
|
||||||
@@ -99,52 +92,25 @@ public class UpdatesDbHelper extends SQLiteOpenHelper {
|
|||||||
values.put(UpdateEntry.COLUMN_NAME_SIZE, update.getFileSize());
|
values.put(UpdateEntry.COLUMN_NAME_SIZE, update.getFileSize());
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean removeUpdate(String downloadId) {
|
public void removeUpdate(String downloadId) {
|
||||||
SQLiteDatabase db = getWritableDatabase();
|
SQLiteDatabase db = getWritableDatabase();
|
||||||
String selection = UpdateEntry.COLUMN_NAME_DOWNLOAD_ID + " = ?";
|
String selection = UpdateEntry.COLUMN_NAME_DOWNLOAD_ID + " = ?";
|
||||||
String[] selectionArgs = {downloadId};
|
String[] selectionArgs = {downloadId};
|
||||||
return db.delete(UpdateEntry.TABLE_NAME, selection, selectionArgs) != 0;
|
db.delete(UpdateEntry.TABLE_NAME, selection, selectionArgs);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean removeUpdate(long rowId) {
|
public void changeUpdateStatus(Update update) {
|
||||||
SQLiteDatabase db = getWritableDatabase();
|
|
||||||
String selection = UpdateEntry._ID + " = " + rowId;
|
|
||||||
return db.delete(UpdateEntry.TABLE_NAME, selection, null) != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean changeUpdateStatus(Update update) {
|
|
||||||
String selection = UpdateEntry.COLUMN_NAME_DOWNLOAD_ID + " = ?";
|
String selection = UpdateEntry.COLUMN_NAME_DOWNLOAD_ID + " = ?";
|
||||||
String[] selectionArgs = {update.getDownloadId()};
|
String[] selectionArgs = {update.getDownloadId()};
|
||||||
return changeUpdateStatus(selection, selectionArgs, update.getPersistentStatus());
|
changeUpdateStatus(selection, selectionArgs, update.getPersistentStatus());
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean changeUpdateStatus(long rowId, int status) {
|
private void changeUpdateStatus(String selection, String[] selectionArgs,
|
||||||
String selection = UpdateEntry._ID + " = " + rowId;
|
|
||||||
return changeUpdateStatus(selection, null, status);
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean changeUpdateStatus(String selection, String[] selectionArgs,
|
|
||||||
int status) {
|
int status) {
|
||||||
SQLiteDatabase db = getWritableDatabase();
|
SQLiteDatabase db = getWritableDatabase();
|
||||||
ContentValues values = new ContentValues();
|
ContentValues values = new ContentValues();
|
||||||
values.put(UpdateEntry.COLUMN_NAME_STATUS, status);
|
values.put(UpdateEntry.COLUMN_NAME_STATUS, status);
|
||||||
return db.update(UpdateEntry.TABLE_NAME, values, selection, selectionArgs) != 0;
|
db.update(UpdateEntry.TABLE_NAME, values, selection, selectionArgs);
|
||||||
}
|
|
||||||
|
|
||||||
public Update getUpdate(long rowId) {
|
|
||||||
String selection = UpdateEntry._ID + " = " + rowId;
|
|
||||||
return getUpdate(selection, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Update getUpdate(String downloadId) {
|
|
||||||
String selection = UpdateEntry.COLUMN_NAME_DOWNLOAD_ID + " = ?";
|
|
||||||
String[] selectionArgs = {downloadId};
|
|
||||||
return getUpdate(selection, selectionArgs);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Update getUpdate(String selection, String[] selectionArgs) {
|
|
||||||
List<Update> updates = getUpdates(selection, selectionArgs);
|
|
||||||
return updates != null ? updates.get(0) : null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Update> getUpdates() {
|
public List<Update> getUpdates() {
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2017 The LineageOS Project
|
* Copyright (C) 2017-2022 The LineageOS Project
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -15,7 +15,6 @@
|
|||||||
*/
|
*/
|
||||||
package org.lineageos.updater;
|
package org.lineageos.updater;
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.IntentFilter;
|
import android.content.IntentFilter;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
@@ -39,6 +38,7 @@ import android.widget.ImageButton;
|
|||||||
import android.widget.ProgressBar;
|
import android.widget.ProgressBar;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
import androidx.appcompat.app.AlertDialog;
|
import androidx.appcompat.app.AlertDialog;
|
||||||
import androidx.appcompat.view.ContextThemeWrapper;
|
import androidx.appcompat.view.ContextThemeWrapper;
|
||||||
import androidx.appcompat.view.menu.MenuBuilder;
|
import androidx.appcompat.view.menu.MenuBuilder;
|
||||||
@@ -77,7 +77,7 @@ public class UpdatesListAdapter extends RecyclerView.Adapter<UpdatesListAdapter.
|
|||||||
private List<String> mDownloadIds;
|
private List<String> mDownloadIds;
|
||||||
private String mSelectedDownload;
|
private String mSelectedDownload;
|
||||||
private UpdaterController mUpdaterController;
|
private UpdaterController mUpdaterController;
|
||||||
private UpdatesListActivity mActivity;
|
private final UpdatesListActivity mActivity;
|
||||||
|
|
||||||
private AlertDialog infoDialog;
|
private AlertDialog infoDialog;
|
||||||
|
|
||||||
@@ -93,27 +93,27 @@ public class UpdatesListAdapter extends RecyclerView.Adapter<UpdatesListAdapter.
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static class ViewHolder extends RecyclerView.ViewHolder {
|
public static class ViewHolder extends RecyclerView.ViewHolder {
|
||||||
private Button mAction;
|
private final Button mAction;
|
||||||
private ImageButton mMenu;
|
private final ImageButton mMenu;
|
||||||
|
|
||||||
private TextView mBuildDate;
|
private final TextView mBuildDate;
|
||||||
private TextView mBuildVersion;
|
private final TextView mBuildVersion;
|
||||||
private TextView mBuildSize;
|
private final TextView mBuildSize;
|
||||||
|
|
||||||
private ProgressBar mProgressBar;
|
private final ProgressBar mProgressBar;
|
||||||
private TextView mProgressText;
|
private final TextView mProgressText;
|
||||||
|
|
||||||
public ViewHolder(final View view) {
|
public ViewHolder(final View view) {
|
||||||
super(view);
|
super(view);
|
||||||
mAction = (Button) view.findViewById(R.id.update_action);
|
mAction = view.findViewById(R.id.update_action);
|
||||||
mMenu = (ImageButton) view.findViewById(R.id.update_menu);
|
mMenu = view.findViewById(R.id.update_menu);
|
||||||
|
|
||||||
mBuildDate = (TextView) view.findViewById(R.id.build_date);
|
mBuildDate = view.findViewById(R.id.build_date);
|
||||||
mBuildVersion = (TextView) view.findViewById(R.id.build_version);
|
mBuildVersion = view.findViewById(R.id.build_version);
|
||||||
mBuildSize = (TextView) view.findViewById(R.id.build_size);
|
mBuildSize = view.findViewById(R.id.build_size);
|
||||||
|
|
||||||
mProgressBar = (ProgressBar) view.findViewById(R.id.progress_bar);
|
mProgressBar = view.findViewById(R.id.progress_bar);
|
||||||
mProgressText = (TextView) view.findViewById(R.id.progress_text);
|
mProgressText = view.findViewById(R.id.progress_text);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -125,6 +125,7 @@ public class UpdatesListAdapter extends RecyclerView.Adapter<UpdatesListAdapter.
|
|||||||
mAlphaDisabledValue = tv.getFloat();
|
mAlphaDisabledValue = tv.getFloat();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
|
public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
|
||||||
View view = LayoutInflater.from(viewGroup.getContext())
|
View view = LayoutInflater.from(viewGroup.getContext())
|
||||||
@@ -133,7 +134,7 @@ public class UpdatesListAdapter extends RecyclerView.Adapter<UpdatesListAdapter.
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onViewDetachedFromWindow(ViewHolder holder) {
|
public void onViewDetachedFromWindow(@NonNull ViewHolder holder) {
|
||||||
super.onViewDetachedFromWindow(holder);
|
super.onViewDetachedFromWindow(holder);
|
||||||
|
|
||||||
if (infoDialog != null) {
|
if (infoDialog != null) {
|
||||||
@@ -191,8 +192,8 @@ public class UpdatesListAdapter extends RecyclerView.Adapter<UpdatesListAdapter.
|
|||||||
String total = Formatter.formatShortFileSize(mActivity, update.getFileSize());
|
String total = Formatter.formatShortFileSize(mActivity, update.getFileSize());
|
||||||
String percentage = NumberFormat.getPercentInstance().format(
|
String percentage = NumberFormat.getPercentInstance().format(
|
||||||
update.getProgress() / 100.f);
|
update.getProgress() / 100.f);
|
||||||
viewHolder.mProgressText.setText(mActivity.getString(R.string.list_download_progress_new,
|
viewHolder.mProgressText.setText(mActivity.getString(
|
||||||
downloaded, total, percentage));
|
R.string.list_download_progress_new, downloaded, total, percentage));
|
||||||
viewHolder.mProgressBar.setIndeterminate(false);
|
viewHolder.mProgressBar.setIndeterminate(false);
|
||||||
viewHolder.mProgressBar.setProgress(update.getProgress());
|
viewHolder.mProgressBar.setProgress(update.getProgress());
|
||||||
}
|
}
|
||||||
@@ -229,7 +230,7 @@ public class UpdatesListAdapter extends RecyclerView.Adapter<UpdatesListAdapter.
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBindViewHolder(final ViewHolder viewHolder, int i) {
|
public void onBindViewHolder(@NonNull final ViewHolder viewHolder, int i) {
|
||||||
if (mDownloadIds == null) {
|
if (mDownloadIds == null) {
|
||||||
viewHolder.mAction.setEnabled(false);
|
viewHolder.mAction.setEnabled(false);
|
||||||
return;
|
return;
|
||||||
@@ -311,7 +312,7 @@ public class UpdatesListAdapter extends RecyclerView.Adapter<UpdatesListAdapter.
|
|||||||
}
|
}
|
||||||
|
|
||||||
View checkboxView = LayoutInflater.from(mActivity).inflate(R.layout.checkbox_view, null);
|
View checkboxView = LayoutInflater.from(mActivity).inflate(R.layout.checkbox_view, null);
|
||||||
CheckBox checkbox = (CheckBox) checkboxView.findViewById(R.id.checkbox);
|
CheckBox checkbox = checkboxView.findViewById(R.id.checkbox);
|
||||||
checkbox.setText(R.string.checkbox_mobile_data_warning);
|
checkbox.setText(R.string.checkbox_mobile_data_warning);
|
||||||
|
|
||||||
new AlertDialog.Builder(mActivity)
|
new AlertDialog.Builder(mActivity)
|
||||||
@@ -370,7 +371,10 @@ public class UpdatesListAdapter extends RecyclerView.Adapter<UpdatesListAdapter.
|
|||||||
final boolean canInstall = Utils.canInstall(update);
|
final boolean canInstall = Utils.canInstall(update);
|
||||||
clickListener = enabled ? view -> {
|
clickListener = enabled ? view -> {
|
||||||
if (canInstall) {
|
if (canInstall) {
|
||||||
getInstallDialog(downloadId).show();
|
AlertDialog.Builder installDialog = getInstallDialog(downloadId);
|
||||||
|
if (installDialog != null) {
|
||||||
|
installDialog.show();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
mActivity.showSnackbar(R.string.snack_update_not_installable,
|
mActivity.showSnackbar(R.string.snack_update_not_installable,
|
||||||
Snackbar.LENGTH_LONG);
|
Snackbar.LENGTH_LONG);
|
||||||
@@ -400,8 +404,7 @@ public class UpdatesListAdapter extends RecyclerView.Adapter<UpdatesListAdapter.
|
|||||||
button.setText(R.string.reboot);
|
button.setText(R.string.reboot);
|
||||||
button.setEnabled(enabled);
|
button.setEnabled(enabled);
|
||||||
clickListener = enabled ? view -> {
|
clickListener = enabled ? view -> {
|
||||||
PowerManager pm =
|
PowerManager pm = mActivity.getSystemService(PowerManager.class);
|
||||||
(PowerManager) mActivity.getSystemService(Context.POWER_SERVICE);
|
|
||||||
pm.reboot(null);
|
pm.reboot(null);
|
||||||
} : null;
|
} : null;
|
||||||
}
|
}
|
||||||
@@ -438,9 +441,7 @@ public class UpdatesListAdapter extends RecyclerView.Adapter<UpdatesListAdapter.
|
|||||||
|
|
||||||
private View.OnClickListener getClickListener(final UpdateInfo update,
|
private View.OnClickListener getClickListener(final UpdateInfo update,
|
||||||
final boolean canDelete, View anchor) {
|
final boolean canDelete, View anchor) {
|
||||||
return view -> {
|
return view -> startActionMode(update, canDelete, anchor);
|
||||||
startActionMode(update, canDelete, anchor);
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private AlertDialog.Builder getInstallDialog(final String downloadId) {
|
private AlertDialog.Builder getInstallDialog(final String downloadId) {
|
||||||
@@ -509,17 +510,17 @@ public class UpdatesListAdapter extends RecyclerView.Adapter<UpdatesListAdapter.
|
|||||||
update.getPersistentStatus() == UpdateStatus.Persistent.VERIFIED);
|
update.getPersistentStatus() == UpdateStatus.Persistent.VERIFIED);
|
||||||
|
|
||||||
popupMenu.setOnMenuItemClickListener(item -> {
|
popupMenu.setOnMenuItemClickListener(item -> {
|
||||||
switch (item.getItemId()) {
|
int itemId = item.getItemId();
|
||||||
case R.id.menu_delete_action:
|
if (itemId == R.id.menu_delete_action) {
|
||||||
getDeleteDialog(update.getDownloadId()).show();
|
getDeleteDialog(update.getDownloadId()).show();
|
||||||
return true;
|
return true;
|
||||||
case R.id.menu_copy_url:
|
} else if (itemId == R.id.menu_copy_url) {
|
||||||
Utils.addToClipboard(mActivity,
|
Utils.addToClipboard(mActivity,
|
||||||
mActivity.getString(R.string.label_download_url),
|
mActivity.getString(R.string.label_download_url),
|
||||||
update.getDownloadUrl(),
|
update.getDownloadUrl(),
|
||||||
mActivity.getString(R.string.toast_download_url_copied));
|
mActivity.getString(R.string.toast_download_url_copied));
|
||||||
return true;
|
return true;
|
||||||
case R.id.menu_export_update:
|
} else if (itemId == R.id.menu_export_update) {
|
||||||
// TODO: start exporting once the permission has been granted
|
// TODO: start exporting once the permission has been granted
|
||||||
boolean hasPermission = PermissionsUtils.checkAndRequestStoragePermission(
|
boolean hasPermission = PermissionsUtils.checkAndRequestStoragePermission(
|
||||||
mActivity, 0);
|
mActivity, 0);
|
||||||
@@ -561,9 +562,11 @@ public class UpdatesListAdapter extends RecyclerView.Adapter<UpdatesListAdapter.
|
|||||||
.setPositiveButton(android.R.string.ok, null)
|
.setPositiveButton(android.R.string.ok, null)
|
||||||
.setMessage(message)
|
.setMessage(message)
|
||||||
.show();
|
.show();
|
||||||
TextView textView = (TextView) infoDialog.findViewById(android.R.id.message);
|
TextView textView = infoDialog.findViewById(android.R.id.message);
|
||||||
|
if (textView != null) {
|
||||||
textView.setMovementMethod(LinkMovementMethod.getInstance());
|
textView.setMovementMethod(LinkMovementMethod.getInstance());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private boolean isBatteryLevelOk() {
|
private boolean isBatteryLevelOk() {
|
||||||
Intent intent = mActivity.registerReceiver(null,
|
Intent intent = mActivity.registerReceiver(null,
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2017 The LineageOS Project
|
* Copyright (C) 2017-2022 The LineageOS Project
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -52,7 +52,7 @@ class ABUpdateInstaller {
|
|||||||
private final Context mContext;
|
private final Context mContext;
|
||||||
private String mDownloadId;
|
private String mDownloadId;
|
||||||
|
|
||||||
private UpdateEngine mUpdateEngine;
|
private final UpdateEngine mUpdateEngine;
|
||||||
private boolean mBound;
|
private boolean mBound;
|
||||||
|
|
||||||
private boolean mFinalizing;
|
private boolean mFinalizing;
|
||||||
@@ -130,11 +130,6 @@ class ABUpdateInstaller {
|
|||||||
return pref.getString(ABUpdateInstaller.PREF_INSTALLING_SUSPENDED_AB_ID, null) != null;
|
return pref.getString(ABUpdateInstaller.PREF_INSTALLING_SUSPENDED_AB_ID, null) != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
static synchronized boolean isInstallingUpdateSuspended(Context context, String downloadId) {
|
|
||||||
SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(context);
|
|
||||||
return downloadId.equals(pref.getString(ABUpdateInstaller.PREF_INSTALLING_SUSPENDED_AB_ID, null));
|
|
||||||
}
|
|
||||||
|
|
||||||
static synchronized boolean isWaitingForReboot(Context context, String downloadId) {
|
static synchronized boolean isWaitingForReboot(Context context, String downloadId) {
|
||||||
String waitingId = PreferenceManager.getDefaultSharedPreferences(context)
|
String waitingId = PreferenceManager.getDefaultSharedPreferences(context)
|
||||||
.getString(Constants.PREF_NEEDS_REBOOT_ID, null);
|
.getString(Constants.PREF_NEEDS_REBOOT_ID, null);
|
||||||
@@ -155,10 +150,10 @@ class ABUpdateInstaller {
|
|||||||
return sInstance;
|
return sInstance;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean install(String downloadId) {
|
public void install(String downloadId) {
|
||||||
if (isInstallingUpdate(mContext)) {
|
if (isInstallingUpdate(mContext)) {
|
||||||
Log.e(TAG, "Already installing an update");
|
Log.e(TAG, "Already installing an update");
|
||||||
return false;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
mDownloadId = downloadId;
|
mDownloadId = downloadId;
|
||||||
@@ -169,7 +164,7 @@ class ABUpdateInstaller {
|
|||||||
mUpdaterController.getActualUpdate(downloadId)
|
mUpdaterController.getActualUpdate(downloadId)
|
||||||
.setStatus(UpdateStatus.INSTALLATION_FAILED);
|
.setStatus(UpdateStatus.INSTALLATION_FAILED);
|
||||||
mUpdaterController.notifyUpdateChange(downloadId);
|
mUpdaterController.notifyUpdateChange(downloadId);
|
||||||
return false;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
long offset;
|
long offset;
|
||||||
@@ -194,7 +189,7 @@ class ABUpdateInstaller {
|
|||||||
mUpdaterController.getActualUpdate(mDownloadId)
|
mUpdaterController.getActualUpdate(mDownloadId)
|
||||||
.setStatus(UpdateStatus.INSTALLATION_FAILED);
|
.setStatus(UpdateStatus.INSTALLATION_FAILED);
|
||||||
mUpdaterController.notifyUpdateChange(mDownloadId);
|
mUpdaterController.notifyUpdateChange(mDownloadId);
|
||||||
return false;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mBound) {
|
if (!mBound) {
|
||||||
@@ -204,7 +199,7 @@ class ABUpdateInstaller {
|
|||||||
mUpdaterController.getActualUpdate(downloadId)
|
mUpdaterController.getActualUpdate(downloadId)
|
||||||
.setStatus(UpdateStatus.INSTALLATION_FAILED);
|
.setStatus(UpdateStatus.INSTALLATION_FAILED);
|
||||||
mUpdaterController.notifyUpdateChange(downloadId);
|
mUpdaterController.notifyUpdateChange(downloadId);
|
||||||
return false;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -222,17 +217,16 @@ class ABUpdateInstaller {
|
|||||||
.putString(PREF_INSTALLING_AB_ID, mDownloadId)
|
.putString(PREF_INSTALLING_AB_ID, mDownloadId)
|
||||||
.apply();
|
.apply();
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean reconnect() {
|
public void reconnect() {
|
||||||
if (!isInstallingUpdate(mContext)) {
|
if (!isInstallingUpdate(mContext)) {
|
||||||
Log.e(TAG, "reconnect: Not installing any update");
|
Log.e(TAG, "reconnect: Not installing any update");
|
||||||
return false;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mBound) {
|
if (mBound) {
|
||||||
return true;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
mDownloadId = PreferenceManager.getDefaultSharedPreferences(mContext)
|
mDownloadId = PreferenceManager.getDefaultSharedPreferences(mContext)
|
||||||
@@ -242,10 +236,8 @@ class ABUpdateInstaller {
|
|||||||
mBound = mUpdateEngine.bind(mUpdateEngineCallback);
|
mBound = mUpdateEngine.bind(mUpdateEngineCallback);
|
||||||
if (!mBound) {
|
if (!mBound) {
|
||||||
Log.e(TAG, "Could not bind");
|
Log.e(TAG, "Could not bind");
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void installationDone(boolean needsReboot) {
|
private void installationDone(boolean needsReboot) {
|
||||||
@@ -257,15 +249,15 @@ class ABUpdateInstaller {
|
|||||||
.apply();
|
.apply();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean cancel() {
|
public void cancel() {
|
||||||
if (!isInstallingUpdate(mContext)) {
|
if (!isInstallingUpdate(mContext)) {
|
||||||
Log.e(TAG, "cancel: Not installing any update");
|
Log.e(TAG, "cancel: Not installing any update");
|
||||||
return false;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mBound) {
|
if (!mBound) {
|
||||||
Log.e(TAG, "Not connected to update engine");
|
Log.e(TAG, "Not connected to update engine");
|
||||||
return false;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
mUpdateEngine.cancel();
|
mUpdateEngine.cancel();
|
||||||
@@ -275,22 +267,21 @@ class ABUpdateInstaller {
|
|||||||
.setStatus(UpdateStatus.INSTALLATION_CANCELLED);
|
.setStatus(UpdateStatus.INSTALLATION_CANCELLED);
|
||||||
mUpdaterController.notifyUpdateChange(mDownloadId);
|
mUpdaterController.notifyUpdateChange(mDownloadId);
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setPerformanceMode(boolean enable) {
|
public void setPerformanceMode(boolean enable) {
|
||||||
mUpdateEngine.setPerformanceMode(enable);
|
mUpdateEngine.setPerformanceMode(enable);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean suspend() {
|
public void suspend() {
|
||||||
if (!isInstallingUpdate(mContext)) {
|
if (!isInstallingUpdate(mContext)) {
|
||||||
Log.e(TAG, "cancel: Not installing any update");
|
Log.e(TAG, "cancel: Not installing any update");
|
||||||
return false;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mBound) {
|
if (!mBound) {
|
||||||
Log.e(TAG, "Not connected to update engine");
|
Log.e(TAG, "Not connected to update engine");
|
||||||
return false;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
mUpdateEngine.suspend();
|
mUpdateEngine.suspend();
|
||||||
@@ -303,18 +294,17 @@ class ABUpdateInstaller {
|
|||||||
.putString(PREF_INSTALLING_SUSPENDED_AB_ID, mDownloadId)
|
.putString(PREF_INSTALLING_SUSPENDED_AB_ID, mDownloadId)
|
||||||
.apply();
|
.apply();
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean resume() {
|
public void resume() {
|
||||||
if (!isInstallingUpdateSuspended(mContext)) {
|
if (!isInstallingUpdateSuspended(mContext)) {
|
||||||
Log.e(TAG, "cancel: No update is suspended");
|
Log.e(TAG, "cancel: No update is suspended");
|
||||||
return false;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mBound) {
|
if (!mBound) {
|
||||||
Log.e(TAG, "Not connected to update engine");
|
Log.e(TAG, "Not connected to update engine");
|
||||||
return false;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
mUpdateEngine.resume();
|
mUpdateEngine.resume();
|
||||||
@@ -329,6 +319,5 @@ class ABUpdateInstaller {
|
|||||||
.remove(PREF_INSTALLING_SUSPENDED_AB_ID)
|
.remove(PREF_INSTALLING_SUSPENDED_AB_ID)
|
||||||
.apply();
|
.apply();
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2017 The LineageOS Project
|
* Copyright (C) 2017-2022 The LineageOS Project
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -113,7 +113,7 @@ class UpdateInstaller {
|
|||||||
Runnable copyUpdateRunnable = new Runnable() {
|
Runnable copyUpdateRunnable = new Runnable() {
|
||||||
private long mLastUpdate = -1;
|
private long mLastUpdate = -1;
|
||||||
|
|
||||||
FileUtils.ProgressCallBack mProgressCallBack = new FileUtils.ProgressCallBack() {
|
final FileUtils.ProgressCallBack mProgressCallBack = new FileUtils.ProgressCallBack() {
|
||||||
@Override
|
@Override
|
||||||
public void update(int progress) {
|
public void update(int progress) {
|
||||||
long now = SystemClock.elapsedRealtime();
|
long now = SystemClock.elapsedRealtime();
|
||||||
@@ -137,12 +137,14 @@ class UpdateInstaller {
|
|||||||
.setStatus(UpdateStatus.INSTALLATION_CANCELLED);
|
.setStatus(UpdateStatus.INSTALLATION_CANCELLED);
|
||||||
mUpdaterController.getActualUpdate(update.getDownloadId())
|
mUpdaterController.getActualUpdate(update.getDownloadId())
|
||||||
.setInstallProgress(0);
|
.setInstallProgress(0);
|
||||||
|
//noinspection ResultOfMethodCallIgnored
|
||||||
uncryptFile.delete();
|
uncryptFile.delete();
|
||||||
} else {
|
} else {
|
||||||
installPackage(uncryptFile, update.getDownloadId());
|
installPackage(uncryptFile, update.getDownloadId());
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Log.e(TAG, "Could not copy update", e);
|
Log.e(TAG, "Could not copy update", e);
|
||||||
|
//noinspection ResultOfMethodCallIgnored
|
||||||
uncryptFile.delete();
|
uncryptFile.delete();
|
||||||
mUpdaterController.getActualUpdate(update.getDownloadId())
|
mUpdaterController.getActualUpdate(update.getDownloadId())
|
||||||
.setStatus(UpdateStatus.INSTALLATION_FAILED);
|
.setStatus(UpdateStatus.INSTALLATION_FAILED);
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2017 The LineageOS Project
|
* Copyright (C) 2017-2022 The LineageOS Project
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -15,6 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.lineageos.updater.controller;
|
package org.lineageos.updater.controller;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.database.sqlite.SQLiteDatabase;
|
import android.database.sqlite.SQLiteDatabase;
|
||||||
@@ -63,11 +64,7 @@ public class UpdaterController {
|
|||||||
private final File mDownloadRoot;
|
private final File mDownloadRoot;
|
||||||
|
|
||||||
private int mActiveDownloads = 0;
|
private int mActiveDownloads = 0;
|
||||||
private Set<String> mVerifyingUpdates = new HashSet<>();
|
private final Set<String> mVerifyingUpdates = new HashSet<>();
|
||||||
|
|
||||||
public static synchronized UpdaterController getInstance() {
|
|
||||||
return sUpdaterController;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static synchronized UpdaterController getInstance(Context context) {
|
protected static synchronized UpdaterController getInstance(Context context) {
|
||||||
if (sUpdaterController == null) {
|
if (sUpdaterController == null) {
|
||||||
@@ -80,8 +77,8 @@ public class UpdaterController {
|
|||||||
mBroadcastManager = LocalBroadcastManager.getInstance(context);
|
mBroadcastManager = LocalBroadcastManager.getInstance(context);
|
||||||
mUpdatesDbHelper = new UpdatesDbHelper(context);
|
mUpdatesDbHelper = new UpdatesDbHelper(context);
|
||||||
mDownloadRoot = Utils.getDownloadPath(context);
|
mDownloadRoot = Utils.getDownloadPath(context);
|
||||||
PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
|
PowerManager powerManager = context.getSystemService(PowerManager.class);
|
||||||
mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "Updater");
|
mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "Updater:wakelock");
|
||||||
mWakeLock.setReferenceCounted(false);
|
mWakeLock.setReferenceCounted(false);
|
||||||
mContext = context.getApplicationContext();
|
mContext = context.getApplicationContext();
|
||||||
|
|
||||||
@@ -92,7 +89,7 @@ public class UpdaterController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class DownloadEntry {
|
private static class DownloadEntry {
|
||||||
final Update mUpdate;
|
final Update mUpdate;
|
||||||
DownloadClient mDownloadClient;
|
DownloadClient mDownloadClient;
|
||||||
private DownloadEntry(Update update) {
|
private DownloadEntry(Update update) {
|
||||||
@@ -100,7 +97,7 @@ public class UpdaterController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Map<String, DownloadEntry> mDownloads = new HashMap<>();
|
private final Map<String, DownloadEntry> mDownloads = new HashMap<>();
|
||||||
|
|
||||||
void notifyUpdateChange(String downloadId) {
|
void notifyUpdateChange(String downloadId) {
|
||||||
Intent intent = new Intent();
|
Intent intent = new Intent();
|
||||||
@@ -156,8 +153,12 @@ public class UpdaterController {
|
|||||||
return new DownloadClient.DownloadCallback() {
|
return new DownloadClient.DownloadCallback() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onResponse(int statusCode, String url, DownloadClient.Headers headers) {
|
public void onResponse(DownloadClient.Headers headers) {
|
||||||
final Update update = mDownloads.get(downloadId).mUpdate;
|
final DownloadEntry entry = mDownloads.get(downloadId);
|
||||||
|
if (entry == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final Update update = entry.mUpdate;
|
||||||
String contentLength = headers.get("Content-Length");
|
String contentLength = headers.get("Content-Length");
|
||||||
if (contentLength != null) {
|
if (contentLength != null) {
|
||||||
try {
|
try {
|
||||||
@@ -177,28 +178,34 @@ public class UpdaterController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSuccess(File destination) {
|
public void onSuccess() {
|
||||||
Log.d(TAG, "Download complete");
|
Log.d(TAG, "Download complete");
|
||||||
Update update = mDownloads.get(downloadId).mUpdate;
|
DownloadEntry entry = mDownloads.get(downloadId);
|
||||||
|
if (entry != null) {
|
||||||
|
Update update = entry.mUpdate;
|
||||||
update.setStatus(UpdateStatus.VERIFYING);
|
update.setStatus(UpdateStatus.VERIFYING);
|
||||||
removeDownloadClient(mDownloads.get(downloadId));
|
removeDownloadClient(entry);
|
||||||
verifyUpdateAsync(downloadId);
|
verifyUpdateAsync(downloadId);
|
||||||
notifyUpdateChange(downloadId);
|
notifyUpdateChange(downloadId);
|
||||||
tryReleaseWakelock();
|
tryReleaseWakelock();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onFailure(boolean cancelled) {
|
public void onFailure(boolean cancelled) {
|
||||||
Update update = mDownloads.get(downloadId).mUpdate;
|
|
||||||
if (cancelled) {
|
if (cancelled) {
|
||||||
Log.d(TAG, "Download cancelled");
|
Log.d(TAG, "Download cancelled");
|
||||||
// Already notified
|
// Already notified
|
||||||
} else {
|
} else {
|
||||||
|
DownloadEntry entry = mDownloads.get(downloadId);
|
||||||
|
if (entry != null) {
|
||||||
|
Update update = entry.mUpdate;
|
||||||
Log.e(TAG, "Download failed");
|
Log.e(TAG, "Download failed");
|
||||||
removeDownloadClient(mDownloads.get(downloadId));
|
removeDownloadClient(entry);
|
||||||
update.setStatus(UpdateStatus.PAUSED_ERROR);
|
update.setStatus(UpdateStatus.PAUSED_ERROR);
|
||||||
notifyUpdateChange(downloadId);
|
notifyUpdateChange(downloadId);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
tryReleaseWakelock();
|
tryReleaseWakelock();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -210,9 +217,12 @@ public class UpdaterController {
|
|||||||
private int mProgress = 0;
|
private int mProgress = 0;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void update(long bytesRead, long contentLength, long speed, long eta,
|
public void update(long bytesRead, long contentLength, long speed, long eta) {
|
||||||
boolean done) {
|
DownloadEntry entry = mDownloads.get(downloadId);
|
||||||
Update update = mDownloads.get(downloadId).mUpdate;
|
if (entry == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Update update = entry.mUpdate;
|
||||||
if (contentLength <= 0) {
|
if (contentLength <= 0) {
|
||||||
if (update.getFileSize() <= 0) {
|
if (update.getFileSize() <= 0) {
|
||||||
return;
|
return;
|
||||||
@@ -224,7 +234,7 @@ public class UpdaterController {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final long now = SystemClock.elapsedRealtime();
|
final long now = SystemClock.elapsedRealtime();
|
||||||
int progress = Math.round(bytesRead * 100 / contentLength);
|
int progress = Math.round(bytesRead * 100f / contentLength);
|
||||||
if (progress != mProgress || mLastUpdate - now > MAX_REPORT_INTERVAL_MS) {
|
if (progress != mProgress || mLastUpdate - now > MAX_REPORT_INTERVAL_MS) {
|
||||||
mProgress = progress;
|
mProgress = progress;
|
||||||
mLastUpdate = now;
|
mLastUpdate = now;
|
||||||
@@ -237,12 +247,16 @@ public class UpdaterController {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressLint("SetWorldReadable")
|
||||||
private void verifyUpdateAsync(final String downloadId) {
|
private void verifyUpdateAsync(final String downloadId) {
|
||||||
mVerifyingUpdates.add(downloadId);
|
mVerifyingUpdates.add(downloadId);
|
||||||
new Thread(() -> {
|
new Thread(() -> {
|
||||||
Update update = mDownloads.get(downloadId).mUpdate;
|
DownloadEntry entry = mDownloads.get(downloadId);
|
||||||
|
if (entry != null) {
|
||||||
|
Update update = entry.mUpdate;
|
||||||
File file = update.getFile();
|
File file = update.getFile();
|
||||||
if (file.exists() && verifyPackage(file)) {
|
if (file.exists() && verifyPackage(file)) {
|
||||||
|
//noinspection ResultOfMethodCallIgnored
|
||||||
file.setReadable(true, false);
|
file.setReadable(true, false);
|
||||||
update.setPersistentStatus(UpdateStatus.Persistent.VERIFIED);
|
update.setPersistentStatus(UpdateStatus.Persistent.VERIFIED);
|
||||||
mUpdatesDbHelper.changeUpdateStatus(update);
|
mUpdatesDbHelper.changeUpdateStatus(update);
|
||||||
@@ -255,6 +269,7 @@ public class UpdaterController {
|
|||||||
}
|
}
|
||||||
mVerifyingUpdates.remove(downloadId);
|
mVerifyingUpdates.remove(downloadId);
|
||||||
notifyUpdateChange(downloadId);
|
notifyUpdateChange(downloadId);
|
||||||
|
}
|
||||||
}).start();
|
}).start();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -266,6 +281,7 @@ public class UpdaterController {
|
|||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Log.e(TAG, "Verification failed", e);
|
Log.e(TAG, "Verification failed", e);
|
||||||
if (file.exists()) {
|
if (file.exists()) {
|
||||||
|
//noinspection ResultOfMethodCallIgnored
|
||||||
file.delete();
|
file.delete();
|
||||||
} else {
|
} else {
|
||||||
// The download was probably stopped. Exit silently
|
// The download was probably stopped. Exit silently
|
||||||
@@ -285,7 +301,7 @@ public class UpdaterController {
|
|||||||
} else if (update.getFileSize() > 0) {
|
} else if (update.getFileSize() > 0) {
|
||||||
update.setStatus(UpdateStatus.PAUSED);
|
update.setStatus(UpdateStatus.PAUSED);
|
||||||
int progress = Math.round(
|
int progress = Math.round(
|
||||||
update.getFile().length() * 100 / update.getFileSize());
|
update.getFile().length() * 100f / update.getFileSize());
|
||||||
update.setProgress(progress);
|
update.setProgress(progress);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -293,15 +309,6 @@ public class UpdaterController {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setUpdatesNotAvailableOnline(List<String> downloadIds) {
|
|
||||||
for (String downloadId : downloadIds) {
|
|
||||||
DownloadEntry update = mDownloads.get(downloadId);
|
|
||||||
if (update != null) {
|
|
||||||
update.mUpdate.setAvailableOnline(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setUpdatesAvailableOnline(List<String> downloadIds, boolean purgeList) {
|
public void setUpdatesAvailableOnline(List<String> downloadIds, boolean purgeList) {
|
||||||
List<String> toRemove = new ArrayList<>();
|
List<String> toRemove = new ArrayList<>();
|
||||||
for (DownloadEntry entry : mDownloads.values()) {
|
for (DownloadEntry entry : mDownloads.values()) {
|
||||||
@@ -327,9 +334,12 @@ public class UpdaterController {
|
|||||||
Log.d(TAG, "Adding download: " + updateInfo.getDownloadId());
|
Log.d(TAG, "Adding download: " + updateInfo.getDownloadId());
|
||||||
if (mDownloads.containsKey(updateInfo.getDownloadId())) {
|
if (mDownloads.containsKey(updateInfo.getDownloadId())) {
|
||||||
Log.d(TAG, "Download (" + updateInfo.getDownloadId() + ") already added");
|
Log.d(TAG, "Download (" + updateInfo.getDownloadId() + ") already added");
|
||||||
Update updateAdded = mDownloads.get(updateInfo.getDownloadId()).mUpdate;
|
DownloadEntry entry = mDownloads.get(updateInfo.getDownloadId());
|
||||||
|
if (entry != null) {
|
||||||
|
Update updateAdded = entry.mUpdate;
|
||||||
updateAdded.setAvailableOnline(availableOnline && updateAdded.getAvailableOnline());
|
updateAdded.setAvailableOnline(availableOnline && updateAdded.getAvailableOnline());
|
||||||
updateAdded.setDownloadUrl(updateInfo.getDownloadUrl());
|
updateAdded.setDownloadUrl(updateInfo.getDownloadUrl());
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
Update update = new Update(updateInfo);
|
Update update = new Update(updateInfo);
|
||||||
@@ -344,12 +354,18 @@ public class UpdaterController {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean startDownload(String downloadId) {
|
@SuppressLint("WakelockTimeout")
|
||||||
|
public void startDownload(String downloadId) {
|
||||||
Log.d(TAG, "Starting " + downloadId);
|
Log.d(TAG, "Starting " + downloadId);
|
||||||
if (!mDownloads.containsKey(downloadId) || isDownloading(downloadId)) {
|
if (!mDownloads.containsKey(downloadId) || isDownloading(downloadId)) {
|
||||||
return false;
|
return;
|
||||||
}
|
}
|
||||||
Update update = mDownloads.get(downloadId).mUpdate;
|
DownloadEntry entry = mDownloads.get(downloadId);
|
||||||
|
if (entry == null) {
|
||||||
|
Log.e(TAG, "Could not get download entry");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Update update = entry.mUpdate;
|
||||||
File destination = new File(mDownloadRoot, update.getName());
|
File destination = new File(mDownloadRoot, update.getName());
|
||||||
if (destination.exists()) {
|
if (destination.exists()) {
|
||||||
destination = Utils.appendSequentialNumber(destination);
|
destination = Utils.appendSequentialNumber(destination);
|
||||||
@@ -369,28 +385,33 @@ public class UpdaterController {
|
|||||||
Log.e(TAG, "Could not build download client");
|
Log.e(TAG, "Could not build download client");
|
||||||
update.setStatus(UpdateStatus.PAUSED_ERROR);
|
update.setStatus(UpdateStatus.PAUSED_ERROR);
|
||||||
notifyUpdateChange(downloadId);
|
notifyUpdateChange(downloadId);
|
||||||
return false;
|
return;
|
||||||
}
|
}
|
||||||
addDownloadClient(mDownloads.get(downloadId), downloadClient);
|
addDownloadClient(entry, downloadClient);
|
||||||
update.setStatus(UpdateStatus.STARTING);
|
update.setStatus(UpdateStatus.STARTING);
|
||||||
notifyUpdateChange(downloadId);
|
notifyUpdateChange(downloadId);
|
||||||
downloadClient.start();
|
downloadClient.start();
|
||||||
mWakeLock.acquire();
|
mWakeLock.acquire();
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean resumeDownload(String downloadId) {
|
@SuppressLint("WakelockTimeout")
|
||||||
|
public void resumeDownload(String downloadId) {
|
||||||
Log.d(TAG, "Resuming " + downloadId);
|
Log.d(TAG, "Resuming " + downloadId);
|
||||||
if (!mDownloads.containsKey(downloadId) || isDownloading(downloadId)) {
|
if (!mDownloads.containsKey(downloadId) || isDownloading(downloadId)) {
|
||||||
return false;
|
return;
|
||||||
}
|
}
|
||||||
Update update = mDownloads.get(downloadId).mUpdate;
|
DownloadEntry entry = mDownloads.get(downloadId);
|
||||||
|
if (entry == null) {
|
||||||
|
Log.e(TAG, "Could not get download entry");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Update update = entry.mUpdate;
|
||||||
File file = update.getFile();
|
File file = update.getFile();
|
||||||
if (file == null || !file.exists()) {
|
if (file == null || !file.exists()) {
|
||||||
Log.e(TAG, "The destination file of " + downloadId + " doesn't exist, can't resume");
|
Log.e(TAG, "The destination file of " + downloadId + " doesn't exist, can't resume");
|
||||||
update.setStatus(UpdateStatus.PAUSED_ERROR);
|
update.setStatus(UpdateStatus.PAUSED_ERROR);
|
||||||
notifyUpdateChange(downloadId);
|
notifyUpdateChange(downloadId);
|
||||||
return false;
|
return;
|
||||||
}
|
}
|
||||||
if (file.exists() && update.getFileSize() > 0 && file.length() >= update.getFileSize()) {
|
if (file.exists() && update.getFileSize() > 0 && file.length() >= update.getFileSize()) {
|
||||||
Log.d(TAG, "File already downloaded, starting verification");
|
Log.d(TAG, "File already downloaded, starting verification");
|
||||||
@@ -411,31 +432,31 @@ public class UpdaterController {
|
|||||||
Log.e(TAG, "Could not build download client");
|
Log.e(TAG, "Could not build download client");
|
||||||
update.setStatus(UpdateStatus.PAUSED_ERROR);
|
update.setStatus(UpdateStatus.PAUSED_ERROR);
|
||||||
notifyUpdateChange(downloadId);
|
notifyUpdateChange(downloadId);
|
||||||
return false;
|
return;
|
||||||
}
|
}
|
||||||
addDownloadClient(mDownloads.get(downloadId), downloadClient);
|
addDownloadClient(entry, downloadClient);
|
||||||
update.setStatus(UpdateStatus.STARTING);
|
update.setStatus(UpdateStatus.STARTING);
|
||||||
notifyUpdateChange(downloadId);
|
notifyUpdateChange(downloadId);
|
||||||
downloadClient.resume();
|
downloadClient.resume();
|
||||||
mWakeLock.acquire();
|
mWakeLock.acquire();
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean pauseDownload(String downloadId) {
|
public void pauseDownload(String downloadId) {
|
||||||
Log.d(TAG, "Pausing " + downloadId);
|
Log.d(TAG, "Pausing " + downloadId);
|
||||||
if (!isDownloading(downloadId)) {
|
if (!isDownloading(downloadId)) {
|
||||||
return false;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
DownloadEntry entry = mDownloads.get(downloadId);
|
DownloadEntry entry = mDownloads.get(downloadId);
|
||||||
|
if (entry != null) {
|
||||||
entry.mDownloadClient.cancel();
|
entry.mDownloadClient.cancel();
|
||||||
removeDownloadClient(entry);
|
removeDownloadClient(entry);
|
||||||
entry.mUpdate.setStatus(UpdateStatus.PAUSED);
|
entry.mUpdate.setStatus(UpdateStatus.PAUSED);
|
||||||
entry.mUpdate.setEta(0);
|
entry.mUpdate.setEta(0);
|
||||||
entry.mUpdate.setSpeed(0);
|
entry.mUpdate.setSpeed(0);
|
||||||
notifyUpdateChange(downloadId);
|
notifyUpdateChange(downloadId);
|
||||||
return true;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void deleteUpdateAsync(final Update update) {
|
private void deleteUpdateAsync(final Update update) {
|
||||||
@@ -448,12 +469,14 @@ public class UpdaterController {
|
|||||||
}).start();
|
}).start();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean deleteUpdate(String downloadId) {
|
public void deleteUpdate(String downloadId) {
|
||||||
Log.d(TAG, "Cancelling " + downloadId);
|
Log.d(TAG, "Cancelling " + downloadId);
|
||||||
if (!mDownloads.containsKey(downloadId) || isDownloading(downloadId)) {
|
if (!mDownloads.containsKey(downloadId) || isDownloading(downloadId)) {
|
||||||
return false;
|
return;
|
||||||
}
|
}
|
||||||
Update update = mDownloads.get(downloadId).mUpdate;
|
DownloadEntry entry = mDownloads.get(downloadId);
|
||||||
|
if (entry != null) {
|
||||||
|
Update update = entry.mUpdate;
|
||||||
update.setStatus(UpdateStatus.DELETED);
|
update.setStatus(UpdateStatus.DELETED);
|
||||||
update.setProgress(0);
|
update.setProgress(0);
|
||||||
update.setPersistentStatus(UpdateStatus.Persistent.UNKNOWN);
|
update.setPersistentStatus(UpdateStatus.Persistent.UNKNOWN);
|
||||||
@@ -466,12 +489,7 @@ public class UpdaterController {
|
|||||||
} else {
|
} else {
|
||||||
notifyUpdateChange(downloadId);
|
notifyUpdateChange(downloadId);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Set<String> getIds() {
|
|
||||||
return mDownloads.keySet();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<UpdateInfo> getUpdates() {
|
public List<UpdateInfo> getUpdates() {
|
||||||
@@ -493,6 +511,7 @@ public class UpdaterController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean isDownloading(String downloadId) {
|
public boolean isDownloading(String downloadId) {
|
||||||
|
//noinspection ConstantConditions
|
||||||
return mDownloads.containsKey(downloadId) &&
|
return mDownloads.containsKey(downloadId) &&
|
||||||
mDownloads.get(downloadId).mDownloadClient != null;
|
mDownloads.get(downloadId).mDownloadClient != null;
|
||||||
}
|
}
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2017 The LineageOS Project
|
* Copyright (C) 2017-2022 The LineageOS Project
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -85,7 +85,7 @@ public class UpdaterService extends Service {
|
|||||||
|
|
||||||
mUpdaterController = UpdaterController.getInstance(this);
|
mUpdaterController = UpdaterController.getInstance(this);
|
||||||
|
|
||||||
mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
|
mNotificationManager = getSystemService(NotificationManager.class);
|
||||||
NotificationChannel notificationChannel = new NotificationChannel(
|
NotificationChannel notificationChannel = new NotificationChannel(
|
||||||
ONGOING_NOTIFICATION_CHANNEL,
|
ONGOING_NOTIFICATION_CHANNEL,
|
||||||
getString(R.string.ongoing_channel_title),
|
getString(R.string.ongoing_channel_title),
|
||||||
@@ -123,8 +123,7 @@ public class UpdaterService extends Service {
|
|||||||
handleInstallProgress(update);
|
handleInstallProgress(update);
|
||||||
} else if (UpdaterController.ACTION_UPDATE_REMOVED.equals(intent.getAction())) {
|
} else if (UpdaterController.ACTION_UPDATE_REMOVED.equals(intent.getAction())) {
|
||||||
Bundle extras = mNotificationBuilder.getExtras();
|
Bundle extras = mNotificationBuilder.getExtras();
|
||||||
if (extras != null && downloadId.equals(
|
if (downloadId.equals(extras.getString(UpdaterController.EXTRA_DOWNLOAD_ID))) {
|
||||||
extras.getString(UpdaterController.EXTRA_DOWNLOAD_ID))) {
|
|
||||||
mNotificationBuilder.setExtras(null);
|
mNotificationBuilder.setExtras(null);
|
||||||
UpdateInfo update = mUpdaterController.getUpdate(downloadId);
|
UpdateInfo update = mUpdaterController.getUpdate(downloadId);
|
||||||
if (update.getStatus() != UpdateStatus.INSTALLED) {
|
if (update.getStatus() != UpdateStatus.INSTALLED) {
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2017 The LineageOS Project
|
* Copyright (C) 2017-2022 The LineageOS Project
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -17,27 +17,23 @@ package org.lineageos.updater.download;
|
|||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
public interface DownloadClient {
|
public interface DownloadClient {
|
||||||
|
|
||||||
interface DownloadCallback {
|
interface DownloadCallback {
|
||||||
void onResponse(int statusCode, String url, Headers headers);
|
void onResponse(Headers headers);
|
||||||
|
|
||||||
void onSuccess(File destination);
|
void onSuccess();
|
||||||
|
|
||||||
void onFailure(boolean cancelled);
|
void onFailure(boolean cancelled);
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ProgressListener {
|
interface ProgressListener {
|
||||||
void update(long bytesRead, long contentLength, long speed, long eta, boolean done);
|
void update(long bytesRead, long contentLength, long speed, long eta);
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Headers {
|
interface Headers {
|
||||||
String get(String name);
|
String get(String name);
|
||||||
|
|
||||||
Map<String, List<String>> getAll();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2017 The LineageOS Project
|
* Copyright (C) 2017-2022 The LineageOS Project
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -51,10 +51,6 @@ public class HttpURLConnectionClient implements DownloadClient {
|
|||||||
return mClient.getHeaderField(name);
|
return mClient.getHeaderField(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Map<String, List<String>> getAll() {
|
|
||||||
return mClient.getHeaderFields();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
HttpURLConnectionClient(String url, File destination,
|
HttpURLConnectionClient(String url, File destination,
|
||||||
@@ -179,8 +175,8 @@ public class HttpURLConnectionClient implements DownloadClient {
|
|||||||
String protocol = mClient.getURL().getProtocol();
|
String protocol = mClient.getURL().getProtocol();
|
||||||
|
|
||||||
class DuplicateLink {
|
class DuplicateLink {
|
||||||
private String mUrl;
|
private final String mUrl;
|
||||||
private int mPriority;
|
private final int mPriority;
|
||||||
private DuplicateLink(String url, int priority) {
|
private DuplicateLink(String url, int priority) {
|
||||||
mUrl = url;
|
mUrl = url;
|
||||||
mPriority = priority;
|
mPriority = priority;
|
||||||
@@ -233,9 +229,11 @@ public class HttpURLConnectionClient implements DownloadClient {
|
|||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
if (duplicates != null && !duplicates.isEmpty()) {
|
if (duplicates != null && !duplicates.isEmpty()) {
|
||||||
DuplicateLink link = duplicates.poll();
|
DuplicateLink link = duplicates.poll();
|
||||||
|
if (link != null) {
|
||||||
duplicates.remove(link);
|
duplicates.remove(link);
|
||||||
newUrl = link.mUrl;
|
newUrl = link.mUrl;
|
||||||
Log.e(TAG, "Using duplicate link " + link.mUrl, e);
|
Log.e(TAG, "Using duplicate link " + link.mUrl, e);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
@@ -255,7 +253,7 @@ public class HttpURLConnectionClient implements DownloadClient {
|
|||||||
responseCode = mClient.getResponseCode();
|
responseCode = mClient.getResponseCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
mCallback.onResponse(responseCode, mClient.getURL().toString(), new Headers());
|
mCallback.onResponse(new Headers());
|
||||||
|
|
||||||
if (mResume && isPartialContentCode(responseCode)) {
|
if (mResume && isPartialContentCode(responseCode)) {
|
||||||
mTotalBytesRead = mDestination.length();
|
mTotalBytesRead = mDestination.length();
|
||||||
@@ -279,12 +277,11 @@ public class HttpURLConnectionClient implements DownloadClient {
|
|||||||
calculateSpeed();
|
calculateSpeed();
|
||||||
calculateEta();
|
calculateEta();
|
||||||
if (mProgressListener != null) {
|
if (mProgressListener != null) {
|
||||||
mProgressListener.update(mTotalBytesRead, mTotalBytes, mSpeed, mEta,
|
mProgressListener.update(mTotalBytesRead, mTotalBytes, mSpeed, mEta);
|
||||||
false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (mProgressListener != null) {
|
if (mProgressListener != null) {
|
||||||
mProgressListener.update(mTotalBytesRead, mTotalBytes, mSpeed, mEta, true);
|
mProgressListener.update(mTotalBytesRead, mTotalBytes, mSpeed, mEta);
|
||||||
}
|
}
|
||||||
|
|
||||||
outputStream.flush();
|
outputStream.flush();
|
||||||
@@ -292,7 +289,7 @@ public class HttpURLConnectionClient implements DownloadClient {
|
|||||||
if (isInterrupted()) {
|
if (isInterrupted()) {
|
||||||
mCallback.onFailure(true);
|
mCallback.onFailure(true);
|
||||||
} else {
|
} else {
|
||||||
mCallback.onSuccess(mDestination);
|
mCallback.onSuccess();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2017 The LineageOS Project
|
* Copyright (C) 2017-2022 The LineageOS Project
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -34,9 +34,9 @@ public class FileUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static class CallbackByteChannel implements ReadableByteChannel {
|
private static class CallbackByteChannel implements ReadableByteChannel {
|
||||||
private ProgressCallBack mCallback;
|
private final ProgressCallBack mCallback;
|
||||||
private long mSize;
|
private final long mSize;
|
||||||
private ReadableByteChannel mReadableByteChannel;
|
private final ReadableByteChannel mReadableByteChannel;
|
||||||
private long mSizeRead;
|
private long mSizeRead;
|
||||||
private int mProgress;
|
private int mProgress;
|
||||||
|
|
||||||
@@ -86,13 +86,10 @@ public class FileUtils {
|
|||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Log.e(TAG, "Could not copy file", e);
|
Log.e(TAG, "Could not copy file", e);
|
||||||
if (destFile.exists()) {
|
if (destFile.exists()) {
|
||||||
|
//noinspection ResultOfMethodCallIgnored
|
||||||
destFile.delete();
|
destFile.delete();
|
||||||
}
|
}
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void copyFile(File sourceFile, File destFile) throws IOException {
|
|
||||||
copyFile(sourceFile, destFile, null);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2017 The LineageOS Project
|
* Copyright (C) 2017-2022 The LineageOS Project
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -36,13 +36,6 @@ public final class StringGenerator {
|
|||||||
return f.format(date);
|
return f.format(date);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getTimeLocalizedUTC(Context context, long unixTimestamp) {
|
|
||||||
DateFormat f = DateFormat.getTimeInstance(DateFormat.SHORT, getCurrentLocale(context));
|
|
||||||
f.setTimeZone(TimeZone.getTimeZone("UTC"));
|
|
||||||
Date date = new Date(unixTimestamp * 1000);
|
|
||||||
return f.format(date);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getDateLocalized(Context context, int dateFormat, long unixTimestamp) {
|
public static String getDateLocalized(Context context, int dateFormat, long unixTimestamp) {
|
||||||
DateFormat f = DateFormat.getDateInstance(dateFormat, getCurrentLocale(context));
|
DateFormat f = DateFormat.getDateInstance(dateFormat, getCurrentLocale(context));
|
||||||
Date date = new Date(unixTimestamp * 1000);
|
Date date = new Date(unixTimestamp * 1000);
|
||||||
@@ -56,13 +49,6 @@ public final class StringGenerator {
|
|||||||
return f.format(date);
|
return f.format(date);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getDateTimeLocalized(Context context, long unixTimestamp) {
|
|
||||||
DateFormat f = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.SHORT,
|
|
||||||
getCurrentLocale(context));
|
|
||||||
Date date = new Date(unixTimestamp * 1000);
|
|
||||||
return f.format(date);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String bytesToMegabytes(Context context, long bytes) {
|
public static String bytesToMegabytes(Context context, long bytes) {
|
||||||
return String.format(getCurrentLocale(context), "%.0f", bytes / 1024.f / 1024.f);
|
return String.format(getCurrentLocale(context), "%.0f", bytes / 1024.f / 1024.f);
|
||||||
}
|
}
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2017-2021 The LineageOS Project
|
* Copyright (C) 2017-2022 The LineageOS Project
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -24,7 +24,6 @@ import android.content.SharedPreferences;
|
|||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.net.ConnectivityManager;
|
import android.net.ConnectivityManager;
|
||||||
import android.net.NetworkInfo;
|
import android.net.NetworkInfo;
|
||||||
import android.os.Environment;
|
|
||||||
import android.os.SystemProperties;
|
import android.os.SystemProperties;
|
||||||
import android.os.storage.StorageManager;
|
import android.os.storage.StorageManager;
|
||||||
import android.preference.PreferenceManager;
|
import android.preference.PreferenceManager;
|
||||||
@@ -122,14 +121,14 @@ public class Utils {
|
|||||||
throws IOException, JSONException {
|
throws IOException, JSONException {
|
||||||
List<UpdateInfo> updates = new ArrayList<>();
|
List<UpdateInfo> updates = new ArrayList<>();
|
||||||
|
|
||||||
String json = "";
|
StringBuilder json = new StringBuilder();
|
||||||
try (BufferedReader br = new BufferedReader(new FileReader(file))) {
|
try (BufferedReader br = new BufferedReader(new FileReader(file))) {
|
||||||
for (String line; (line = br.readLine()) != null;) {
|
for (String line; (line = br.readLine()) != null;) {
|
||||||
json += line;
|
json.append(line);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
JSONObject obj = new JSONObject(json);
|
JSONObject obj = new JSONObject(json.toString());
|
||||||
JSONArray updatesList = obj.getJSONArray("response");
|
JSONArray updatesList = obj.getJSONArray("response");
|
||||||
for (int i = 0; i < updatesList.length(); i++) {
|
for (int i = 0; i < updatesList.length(); i++) {
|
||||||
if (updatesList.isNull(i)) {
|
if (updatesList.isNull(i)) {
|
||||||
@@ -186,15 +185,13 @@ public class Utils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isNetworkAvailable(Context context) {
|
public static boolean isNetworkAvailable(Context context) {
|
||||||
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(
|
ConnectivityManager cm = context.getSystemService(ConnectivityManager.class);
|
||||||
Context.CONNECTIVITY_SERVICE);
|
|
||||||
NetworkInfo info = cm.getActiveNetworkInfo();
|
NetworkInfo info = cm.getActiveNetworkInfo();
|
||||||
return !(info == null || !info.isConnected() || !info.isAvailable());
|
return !(info == null || !info.isConnected() || !info.isAvailable());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isOnWifiOrEthernet(Context context) {
|
public static boolean isOnWifiOrEthernet(Context context) {
|
||||||
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(
|
ConnectivityManager cm = context.getSystemService(ConnectivityManager.class);
|
||||||
Context.CONNECTIVITY_SERVICE);
|
|
||||||
NetworkInfo info = cm.getActiveNetworkInfo();
|
NetworkInfo info = cm.getActiveNetworkInfo();
|
||||||
return (info != null && (info.getType() == ConnectivityManager.TYPE_ETHERNET
|
return (info != null && (info.getType() == ConnectivityManager.TYPE_ETHERNET
|
||||||
|| info.getType() == ConnectivityManager.TYPE_WIFI));
|
|| info.getType() == ConnectivityManager.TYPE_WIFI));
|
||||||
@@ -206,8 +203,6 @@ public class Utils {
|
|||||||
* @param oldJson old update list
|
* @param oldJson old update list
|
||||||
* @param newJson new update list
|
* @param newJson new update list
|
||||||
* @return true if newJson has at least a compatible update not available in oldJson
|
* @return true if newJson has at least a compatible update not available in oldJson
|
||||||
* @throws IOException
|
|
||||||
* @throws JSONException
|
|
||||||
*/
|
*/
|
||||||
public static boolean checkForNewUpdates(File oldJson, File newJson)
|
public static boolean checkForNewUpdates(File oldJson, File newJson)
|
||||||
throws IOException, JSONException {
|
throws IOException, JSONException {
|
||||||
@@ -264,6 +259,7 @@ public class Utils {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (File file : uncryptFiles) {
|
for (File file : uncryptFiles) {
|
||||||
|
//noinspection ResultOfMethodCallIgnored
|
||||||
file.delete();
|
file.delete();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -273,7 +269,6 @@ public class Utils {
|
|||||||
* the user can't access and that might have stale files. This can happen if
|
* the user can't access and that might have stale files. This can happen if
|
||||||
* the data of the application are wiped.
|
* the data of the application are wiped.
|
||||||
*
|
*
|
||||||
* @param context
|
|
||||||
*/
|
*/
|
||||||
public static void cleanupDownloadsDir(Context context) {
|
public static void cleanupDownloadsDir(Context context) {
|
||||||
File downloadPath = getDownloadPath(context);
|
File downloadPath = getDownloadPath(context);
|
||||||
@@ -290,6 +285,7 @@ public class Utils {
|
|||||||
lastUpdatePath != null) {
|
lastUpdatePath != null) {
|
||||||
File lastUpdate = new File(lastUpdatePath);
|
File lastUpdate = new File(lastUpdatePath);
|
||||||
if (lastUpdate.exists()) {
|
if (lastUpdate.exists()) {
|
||||||
|
//noinspection ResultOfMethodCallIgnored
|
||||||
lastUpdate.delete();
|
lastUpdate.delete();
|
||||||
// Remove the pref not to delete the file if re-downloaded
|
// Remove the pref not to delete the file if re-downloaded
|
||||||
preferences.edit().remove(Constants.PREF_INSTALL_PACKAGE_PATH).apply();
|
preferences.edit().remove(Constants.PREF_INSTALL_PACKAGE_PATH).apply();
|
||||||
@@ -319,6 +315,7 @@ public class Utils {
|
|||||||
for (File file : files) {
|
for (File file : files) {
|
||||||
if (!knownPaths.contains(file.getAbsolutePath())) {
|
if (!knownPaths.contains(file.getAbsolutePath())) {
|
||||||
Log.d(TAG, "Deleting " + file.getAbsolutePath());
|
Log.d(TAG, "Deleting " + file.getAbsolutePath());
|
||||||
|
//noinspection ResultOfMethodCallIgnored
|
||||||
file.delete();
|
file.delete();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -367,7 +364,8 @@ public class Utils {
|
|||||||
return context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN);
|
return context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void addToClipboard(Context context, String label, String text, String toastMessage) {
|
public static void addToClipboard(Context context, String label, String text,
|
||||||
|
String toastMessage) {
|
||||||
ClipboardManager clipboard = (ClipboardManager) context.getSystemService(
|
ClipboardManager clipboard = (ClipboardManager) context.getSystemService(
|
||||||
Context.CLIPBOARD_SERVICE);
|
Context.CLIPBOARD_SERVICE);
|
||||||
ClipData clip = ClipData.newPlainText(label, text);
|
ClipData clip = ClipData.newPlainText(label, text);
|
||||||
|
@@ -32,10 +32,6 @@ public class Update extends UpdateBase implements UpdateInfo {
|
|||||||
public Update() {
|
public Update() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public Update(UpdateBaseInfo update) {
|
|
||||||
super(update);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Update(UpdateInfo update) {
|
public Update(UpdateInfo update) {
|
||||||
super(update);
|
super(update);
|
||||||
mStatus = update.getStatus();
|
mStatus = update.getStatus();
|
||||||
|
@@ -19,7 +19,6 @@ public enum UpdateStatus {
|
|||||||
UNKNOWN,
|
UNKNOWN,
|
||||||
STARTING,
|
STARTING,
|
||||||
DOWNLOADING,
|
DOWNLOADING,
|
||||||
DOWNLOADED,
|
|
||||||
PAUSED,
|
PAUSED,
|
||||||
PAUSED_ERROR,
|
PAUSED_ERROR,
|
||||||
DELETED,
|
DELETED,
|
||||||
|
@@ -4,6 +4,7 @@ import android.content.Context;
|
|||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
import androidx.coordinatorlayout.widget.CoordinatorLayout;
|
import androidx.coordinatorlayout.widget.CoordinatorLayout;
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
@@ -21,8 +22,9 @@ public final class FlingBehavior extends AppBarLayout.Behavior {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onNestedFling(CoordinatorLayout coordinatorLayout, AppBarLayout child,
|
public boolean onNestedFling(@NonNull CoordinatorLayout coordinatorLayout,
|
||||||
View target, float velocityX, float velocityY, boolean consumed) {
|
@NonNull AppBarLayout child, @NonNull View target,
|
||||||
|
float velocityX, float velocityY, boolean consumed) {
|
||||||
if (velocityY > 0 && !isPositive || velocityY < 0 && isPositive) {
|
if (velocityY > 0 && !isPositive || velocityY < 0 && isPositive) {
|
||||||
velocityY = velocityY * -1;
|
velocityY = velocityY * -1;
|
||||||
}
|
}
|
||||||
@@ -37,9 +39,10 @@ public final class FlingBehavior extends AppBarLayout.Behavior {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onNestedPreScroll(CoordinatorLayout coordinatorLayout, AppBarLayout child,
|
public void onNestedPreScroll(@NonNull CoordinatorLayout coordinatorLayout,
|
||||||
View target, int dx, int dy, int[] consumed) {
|
@NonNull AppBarLayout child, @NonNull View target,
|
||||||
super.onNestedPreScroll(coordinatorLayout, child, target, dx, dy, consumed);
|
int dx, int dy, @NonNull int[] consumed, int type) {
|
||||||
|
super.onNestedPreScroll(coordinatorLayout, child, target, dx, dy, consumed, type);
|
||||||
isPositive = dy > 0;
|
isPositive = dy > 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user